package PleskX; # # Agent interface: # # ::checkHost() # # ::new($storagePolicy, $dumpStatusPolicy, $agentsSharedDir) # # ->setDumpType(FULL [default] | SHALLOW | CONFIGURATION | ONLY_MAIL) # # ->selectDomains(@domains) # ->selectClients(@clients) # ->selectAll() # ->selectAllDomains() # ->selectServerSettings() # # ->excludeDomains(@domains) # ->excludeClients(@clients) # # ->dump() # # Plesk agent interface: # # ->setDescription() # use strict; use PleskVersion; use PleskMaxVersion; use PleskStructure; use Status; use SiteApp; use SiteApp10; use Mailman; use AgentConfig; use StopWatch; use Logging; #require "agent.include.pl"; # makePasswordNode, generateDumpId, XmlNode, makeXmlNode, # makeMIMEBase64, urlDecode, addPermissionNode, addMailuserPermissionNode, # getSqlList use vars qw|@ISA|; sub new { my $self = {}; bless( $self, shift ); $self->_init(@_); return $self; } sub checkHost { my @problems; if ( !AgentConfig::init() ) { push @problems, "Unable to find /etc/psa/psa.conf configuration file"; } else { eval { PleskVersion::init( AgentConfig::get('PRODUCT_ROOT_D') ) }; if ($@) { push @problems, $@; } else { if ( !PleskVersion::isSupported() ) { if ( PleskVersion::atLeast( 2, 5, 0 ) ) { push @problems, "Migration from version >= " . PleskMaxVersion::get() . " is not supported"; } else { push @problems, "Migration from version < 2.5.0 is not supported"; } } } if ( !defined AgentConfig::iconvBin() ) { push @problems, "No 'iconv' binary found on the host"; } } return @problems; } sub getDomainRoot { my ($self, $domainAsciiName) = @_; my $domainRoot = AgentConfig::get("HTTPD_VHOSTS_D") . "/$domainAsciiName"; return $domainRoot; } sub getDefaultWebspaceRoot { getDomainRoot(@_); } sub getWebspaceRoot { my ($self, $domainAsciiName) = @_; my $domainRoot = $self->getDomainRoot($domainAsciiName); return $domainRoot unless ( PleskVersion::atLeast( 10, 0, 0 ) and not PleskVersion::isSmb() ); my $home; my $sql = "SELECT s.home FROM sys_users s, hosting h, domains d WHERE h.sys_user_id=s.id AND d.id=h.dom_id AND d.name='$domainAsciiName'"; if ( $self->{dbh}->execute_rownum($sql) and my $ptrRow = $self->{dbh}->fetchrow() ) { $home = $ptrRow->[0]; } $self->{dbh}->finish(); if ($home ne $domainRoot) { return $home; } return $domainRoot; } sub getSubroutineRef { my $self = shift; my $name = shift; my $ret = \&{ref($self->{packer}) . "::" . $name}; return $ret; } # --- Public instance methods --- sub _init { my ( $self, $storagePolicy, $dumpStatusPolicy, $agentsSharedDir, $skipLogs ) = @_; $self->{collectStatistics} = $self->getCollectStatistics(); if ($self->{collectStatistics}) { $self->{stopWatch} = StopWatch->new(); $self->{stopWatch}->createMarker("all"); use StopWatchPacker; $self->{packer} = StopWatchPacker->new( PleskMaxVersion::get(), $storagePolicy ); } else { use Packer; $self->{packer} = Packer->new( PleskMaxVersion::get(), $storagePolicy ); } $self->{dump_status} = $dumpStatusPolicy; $self->{skip_logs} = $skipLogs; $self->{configuration_dump} = undef; $self->{shallow_dump} = undef; $self->{only_mail_dump} = undef; $self->{only_hosting_dump} = undef; $self->{description} = undef; $self->{suspend} = undef; $self->{suspendedDomain} = undef; $self->{get_size} = undef; $self->{dump_vhost} = 0; $self->{dump_full_mail} = 0; $self->{dumped_domains} = []; $self->{dumped_clients} = []; #----- # Array of custom buttons IDs which are dumped within site applications #----- $self->{skip_custom_buttons} = []; AgentConfig::init() or die "Error: Plesk config file 'psa.conf' is not found\n"; AgentConfig::setSharedDir($agentsSharedDir); AgentConfig::tarBin(); # Pre-caching of values AgentConfig::mysqlBin(); PleskVersion::init( AgentConfig::get('PRODUCT_ROOT_D') ); $self->{base64} = Packer::makeMIMEBase64(); $self->{dbh} = Db::Connection::getConnection( 'type' => 'mysql', 'user' => 'admin', 'password' => AgentConfig::get('password'), 'name' => 'psa', 'host' => 'localhost', 'utf8names' => PleskVersion::atLeast( 8, 0, 0 ) ); if ($self->{collectStatistics}) { $self->{dbh}->startCollectStatistics(); } PleskStructure::init( $self->{dbh} ); if ( PleskVersion::atLeast( 7, 1, 0 ) ) { Encoding::setDefaultEncoding("UTF-8"); } } sub getCollectStatistics { my $envVal = $ENV{'COLLECT_BACKUP_STAT'}; if ($envVal) { return $envVal; } return 0; } sub turnOffMigrationMode{ my ($self) = @_; $self->{packer}->turnOffMigrationMode(); } sub setDumpWholeVHost{ my ($self) = @_; $self->{dump_vhost} = 1; } sub setDumpWholeMail{ my ($self) = @_; $self->{dump_full_mail} = 1; } sub setSizeMode{ my ($self) = @_; $self->{get_size} = 1; Logging::setVerbosity(4); } sub setContentTransport{ my $self = shift; my $contentTransportType = shift; $self->{packer}->setContentTransport($contentTransportType, @_) } use vars qw|$FULL $SHALLOW $CONFIGURATION $ONLY_MAIL $ONLY_HOSTING $INCLUDE_APP_DISTRIB|; $FULL = 0; $SHALLOW = 1; $CONFIGURATION = 2; $ONLY_MAIL = 4; $ONLY_HOSTING = 8; $INCLUDE_APP_DISTRIB = 16; sub setBackupProfileFileName{ my ($self, $profileName, $profileId ) = @_; die "Invalid backup profile name '$profileName'\n" if index( $profileName, '/' )>=0; $self->{packer}->setBackupProfileFileName( $profileName, $profileId ) if $profileName; } sub setBackupOwnerGuid{ my ($self, $ownerGuid, $ownertype ) = @_; $ownerGuid = PleskStructure::getAdminGuid() if not $ownerGuid; $ownertype = 'server' if not $ownertype; $self->{packer}->setBackupOwnerGuid( $ownerGuid, $ownertype ); } sub getBackupOwnerGuid{ my ($self) = @_; $self->{packer}->getBackupOwnerGuid(); } sub getMainServerIp{ AgentConfig::init() or die "Error: Plesk config file 'psa.conf' is not found\n"; PleskVersion::init( AgentConfig::get('PRODUCT_ROOT_D') ); my $dbh = Db::Connection::getConnection( 'type' => 'mysql', 'user' => 'admin', 'password' => AgentConfig::get('password'), 'name' => 'psa', 'host' => 'localhost', 'utf8names' => PleskVersion::atLeast( 8, 0, 0 ) ); PleskStructure::fastInit( $dbh ); $dbh->disconnect(); return PleskStructure::getDefaultIp(); } sub setDumpType { my ( $self, $type ) = @_; if ( $type & $SHALLOW ) { $self->{shallow_dump} = 1; } if ( $type & $CONFIGURATION ) { $self->{configuration_dump} = 1; } if ( $type & $ONLY_MAIL ) { $self->{only_mail_dump} = 1; $self->{only_hosting_dump} = undef; } if ( $type & $ONLY_HOSTING ) { $self->{only_hosting_dump} = 1; $self->{only_mail_dump} = undef; } if ( $type & $INCLUDE_APP_DISTRIB) { $self->{include_app_distrib} = 1; } } sub setDescription { my ( $self, $description ) = @_; $self->{description} = $description; } sub selectDomains { my ( $self, @inputDomains ) = @_; @inputDomains = sort { $a cmp $b } @inputDomains; my @pleskDomains = sort { $a cmp $b } PleskStructure::getDomains(); my @missingDomains = arrayDifference( \@inputDomains, \@pleskDomains ); if (@missingDomains) { my $msg = "The following domains were not found on the host: " . ( join ",", @missingDomains ); print STDERR "$msg\n"; Packer::printToError( $msg ); @inputDomains = arrayIntersection( \@inputDomains, \@pleskDomains ); } $self->{domains} = \@inputDomains if @inputDomains; } sub selectDomainsById { my ( $self, @inputDomains ) = @_; my @pleskDomains = PleskStructure::getDomainsFromId( \@inputDomains ); if( scalar(@inputDomains)>0 ){ my $msg = "The following domain id's were not found on the host: " . ( join ",", @inputDomains ); print STDERR "$msg\n"; Packer::printToError( $msg ); } $self->selectDomains( @pleskDomains ) if @pleskDomains; } sub selectClients { my ( $self, @inputClients ) = @_; @inputClients = sort { $a cmp $b } @inputClients; my @pleskClients = sort { $a cmp $b } PleskStructure::getClients(); my @missingClients = arrayDifference( \@inputClients, \@pleskClients ); if (@missingClients) { my $msg = "The following clients were not found on the host: " . ( join ",", @missingClients ); print STDERR "$msg\n"; Packer::printToError( $msg ); @inputClients = arrayIntersection( \@inputClients, \@pleskClients ); } $self->_selectClients( \@inputClients ) if @inputClients; } sub selectClientsById { my ( $self, @inputClients ) = @_; my @pleskClients = PleskStructure::getClientsFromId( \@inputClients); if( scalar(@inputClients)>0 ){ my $msg = "The following clients id's were not found on the host: " . ( join ",", @inputClients ); print STDERR "$msg\n"; Packer::printToError( $msg ); } $self->selectClients( @pleskClients ) if @pleskClients; } sub selectResellers { my ( $self, @inputResellers ) = @_; @inputResellers = sort { $a cmp $b } @inputResellers; my @pleskResellers = sort { $a cmp $b } PleskStructure::getResellers(); my @missingResellers = arrayDifference( \@inputResellers, \@pleskResellers ); if (@missingResellers) { my $msg = "The following resellers were not found on the host: " . ( join ",", @missingResellers ); print STDERR "$msg\n"; Packer::printToError( $msg ); @inputResellers = arrayIntersection( \@inputResellers, \@pleskResellers ); } $self->_selectClients( \@inputResellers ) if @inputResellers; } sub selectResellersById { my ( $self, @inputResellers ) = @_; my @pleskResellers = PleskStructure::getResellersFromId( \@inputResellers); if( scalar(@inputResellers)>0 ){ my $msg = "The following reseller id's were not found on the host: " . ( join ",", @inputResellers ); print STDERR "$msg\n"; Packer::printToError( $msg ); } $self->selectResellers( @pleskResellers ) if @pleskResellers; } sub _selectClients { my( $self, $logins ) = @_; my @clients; my @resellers; my $admin = 0; foreach my $client(@{$logins}){ my $clType = PleskStructure::getClientType( $client ); push @clients, $client if $clType eq 'client'; push @resellers, $client if $clType eq 'reseller'; $admin = 1 if $clType eq 'admin'; } $self->{resellers} = \@resellers if scalar(@resellers)>0; $self->{clients} = \@clients if scalar(@clients)>0; $self->{dump_all} = 1 if $admin; } sub excludeDomains { my ( $self, @inputDomains ) = @_; @inputDomains = PleskStructure::getDomains() if scalar(@inputDomains)==0; @inputDomains = sort { $a cmp $b } @inputDomains; $self->{exclude_domains} = \@inputDomains; $self->{domains} = [arrayDifference($self->{domains}, \@inputDomains)] if exists $self->{domains}; } sub excludeClients { my ( $self, @inputClients ) = @_; @inputClients = PleskStructure::getClients() if scalar(@inputClients)==0; @inputClients = sort { $a cmp $b } @inputClients; $self->{exclude_clients} = \@inputClients; $self->{clients} = [arrayDifference($self->{clients}, \@inputClients)] if exists $self->{clients}; } sub excludeResellers { my ( $self, @inputResellers ) = @_; @inputResellers = PleskStructure::getResellers() if scalar(@inputResellers)==0; @inputResellers = sort { $a cmp $b } @inputResellers; $self->{exclude_resellers} = \@inputResellers; $self->{resellers} = [arrayDifference($self->{resellers}, \@inputResellers)] if exists $self->{resellers}; } sub domainExcluded{ my ($self, $name ) = @_; if( exists $self->{exclude_domains} ){ foreach my $domain( @{$self->{exclude_domains}} ){ return 1 if $domain eq $name; } } return 0; } sub clientExcluded{ my ($self, $name ) = @_; if( exists $self->{exclude_clients} ){ foreach my $client( @{$self->{exclude_clients}} ){ return 1 if $client eq $name; } } return 0; } sub resellerExcluded{ my ($self, $name ) = @_; if( exists $self->{exclude_resellers} ){ foreach my $reseller( @{$self->{exclude_resellers}} ){ return 1 if $reseller eq $name; } } return 0; } sub selectAll { my ($self) = @_; #my @pleskClients = sort PleskStructure::sortClients PleskStructure::getAdminClients(); #$self->{clients} = \@pleskClients; $self->{dump_all} = 1; } sub selectAllResellers { my ($self) = @_; my @pleskResellers = sort { $a cmp $b } PleskStructure::getResellers(); $self->{resellers} = \@pleskResellers; } sub selectAllClients { my ($self) = @_; my @pleskClients = sort { $a cmp $b } PleskStructure::getClients(); $self->{clients} = \@pleskClients; } sub selectAllDomains { my ($self) = @_; my @pleskDomains = sort { $a cmp $b } PleskStructure::getDomains(); $self->{domains} = \@pleskDomains; } sub selectServerSettings { my ($self) = @_; $self->{server_settings} = 1; } sub getSuspendCommand{ return AgentConfig::get("PRODUCT_ROOT_D") . "/bin/sw-engine-pleskrun " . AgentConfig::get("PRODUCT_ROOT_D") . "/admin/plib/backup/suspend_handler/SuspendHandlerRunner.php"; } sub getLicenseCommand { return AgentConfig::get("PRODUCT_ROOT_D") . "/bin/sw-engine-pleskrun " . AgentConfig::get("PRODUCT_ROOT_D") . "/admin/plib/api-cli/license.php"; } sub setSuspend{ my ( $self, $suspend, $suspendSid ) = @_; $self->{suspend} = undef; if( $suspend ){ if( $suspendSid ){ $self->{suspend} = 1; $self->{suspendSid} = $suspendSid; } else{ Logging::error( "Suspend session id is unkwnown. Suspend will be unavailable." ); } } } sub suspendDomain{ my ($self, $domain ) = @_; return if not $self->{suspend}; $self->unSuspendDomain(); Logging::info( "Suspend domain '$domain'" ); my $cmd = getSuspendCommand() . " suspend $domain $self->{suspendSid}"; Logging::info( "Exec: $cmd" ); my $ret = `$cmd`; my $retCode = $? >> 8; if( $retCode!=0 ){ Logging::error( "Cannot suspend domain '$domain' (ErrorCode: $retCode, STDOUT:$ret) [Error:$!]. This is not fatal error!" ); return; } $self->{suspendedDomain} = $domain; } sub unSuspendDomain{ my ($self ) = @_; return if not $self->{suspend}; return if not $self->{suspendedDomain}; my $domain = $self->{suspendedDomain}; Logging::info( "Resume domain '$domain'" ); my $cmd = getSuspendCommand() . " unsuspend $domain $self->{suspendSid}"; Logging::info( "Exec: $cmd" ); my $ret = `$cmd`; my $retCode = $? >> 8; if( $retCode!=0 ){ Logging::error( "Cannot resume domain '$domain' (ErrorCode: $retCode, STDOUT:$ret) [Error:$!]." ); Logging::error( "The domain '$domain' may be inaccessible after backup. Please, resume it manually!" ); } $self->{suspendedDomain} = undef; } sub Cleanup{ my $self = shift; $self->unSuspendDomain(); } sub dump { my ($self) = @_; $self->{packer}->tunOffContent() if $self->{configuration_dump}; my $panelMode = $self->getPanelMode(); $self->{packer}->setRoot( $self->{description}, $self->{configuration_dump} ? 0: 1, defined($panelMode) ? $panelMode : PleskVersion::isSmb() ? 'smb' : 'panel' ); if( exists $self->{dump_all} ) { $self->createFullDump(); if (PleskVersion::isSmb() && $self->{configuration_dump}) { $self->addAllRoles(); $self->addAllUsers(); } $self->makeServerNode() if exists $self->{server_settings}; $self->{packer}->addServerNodeToDump(); } else{ my $done; $self->beginWriteStatus(); if (exists $self->{resellers}){ $self->createResellersDump(); $done = 1; } if (exists $self->{clients}) { $self->createClientsDump(); $done = 1; } if ( exists $self->{domains} ) { $self->createDomainsDump(); $done = 1; } $self->{packer}->addRootRoles(); $self->{packer}->addRootUsers(); $self->{packer}->addRootDomains(); if( exists $self->{server_settings} ){ $self->makeServerNode(); $done = 1; } $self->{packer}->addServerNodeToDump(); $self->{dump_status}->finishObjects(); die "No objects to dump found" if not $done; } $self->unSuspendDomain(); my $ret = $self->{packer}->finish(); if ($self->{collectStatistics}) { $self->writeStatistics(); } return $ret; } sub getSize { my ($self) = @_; Logging::info("Get backup size for selected objects"); if ( $self->{configuration_dump} ) { Logging::info("Get backup size finished. Configuration-only mode detected. Backup size is reported as 0 bytes"); return 0; } my $size = 0; if ( exists $self->{dump_all} ) { my @resellers = sort { $a cmp $b } PleskStructure::getResellers(); @resellers = $self->filterSelectedResellers( \@resellers ); foreach my $reseller ( @resellers ) { $size += $self->getSelectedResellerBackupSize( $reseller ); } my @clients = sort { $a cmp $b } PleskStructure::getAdminClients(); @clients = $self->filterSelectedClients( \@clients ); foreach my $client ( @clients ) { if( PleskStructure::getClientType( $client ) eq 'client' ){ $size += $self->getSelectedClientBackupSize( $client ); } } my @adminDomains = PleskStructure::getAdminDomains(); @adminDomains = $self->filterSelectedDomains( \@adminDomains ); foreach my $domainName(@adminDomains) { $size += $self->getDomainBackupSize( $domainName ); } } elsif ( exists $self->{resellers} ){ foreach my $reseller ( @{ $self->{resellers} } ) { $size += $self->getSelectedResellerBackupSize( $reseller ); } } elsif ( exists $self->{clients} ) { foreach my $client ( @{ $self->{clients} } ) { $size += $self->getSelectedClientBackupSize( $client ); } } elsif ( exists $self->{domains} ) { foreach my $domain ( @{$self->{domains}} ) { $size += $self->getDomainBackupSize( $domain ); } } if( exists $self->{server_settings} ){ $size += $self->getServerSettingsBackupSize(); } Logging::info("Get backup size finished. Backup size of selected objects is $size bytes"); return $size; } sub getSelectedResellerBackupSize { my ($self, $reseller) = @_; my $size = 0; $size += $self->getSelectedClientBackupSize($reseller); my @myclients = sort { $a cmp $b } PleskStructure::getMyClients($reseller); @myclients = $self->filterSelectedClients( \@myclients ); foreach my $client ( @myclients ) { $size += $self->getSelectedClientBackupSize( $client ); } return $size; } sub getSelectedClientBackupSize { my ($self, $client ) = @_; my $size = 0; my @mydomains = sort { $a cmp $b } PleskStructure::getDomainsForClient($client); @mydomains = $self->filterSelectedDomains( \@mydomains ); $size += $self->getClientBackupSize($client); foreach my $domain ( @mydomains ) { $size += $self->getDomainBackupSize( $domain ); } return $size; } sub getDomainBackupSize { my ($self, $domain ) = @_; my $size = 0; Logging::info("Get backup size for domain '$domain'"); if ( $self->{configuration_dump} ) { Logging::info("Get backup size for domain '$domain' finished. Configuration-only mode detected. Size is $size bytes."); return 0; } my $domainId = PleskStructure::getDomainId($domain); if ( not defined $domainId ) { Logging::error("Failed to get domain id for '$domain'"); return 0; } my $sql = "SELECT name FROM domains WHERE id=$domainId"; my $domainAsciiName; if ( $self->{dbh}->execute_rownum($sql) and my $ptrRow = $self->{dbh}->fetchrow() ) { $domainAsciiName = $ptrRow->[0]; } $self->{dbh}->finish(); if ( not defined $domainAsciiName ) { Logging::error("Failed to get domain name for '$domain'"); return 0; } if ( !$self->{only_hosting_dump} and !$self->{only_mail_dump} ) { $size += $self->getDomainDbSize($domain, $domainId); } if ( !$self->{only_hosting_dump} ) { $size += $self->getDomainMailSize($domain, $domainAsciiName, $domainId); $size += $self->getDomainMaillistsSize($domain, $domainId); } if ( !$self->{only_mail_dump} ) { $size += $self->getDomainTomcatSize($domain, $domainId, $domainAsciiName); $size += $self->getDomainPhostingSize($domain, $domainId, $domainAsciiName); } if ( !$self->{only_mail_dump} and PleskVersion::atLeast( 7, 1, 0 ) ) { $size += $self->getDomainCustomButtonsSize($domain, $domainId); } Logging::info("Get backup size for domain '$domain' finished. Size is $size bytes."); return $size; } sub getDomainCustomButtonsSize{ my ($self, $domain, $domainId ) = @_; my $size = 0; Logging::debug("Domain '$domain': ". (caller(0))[3]." started."); my @buttonIds = $self->getCustomButtonIdsByOwner71('domain-admin', $domainId); foreach my $buttonId ( @buttonIds ) { $size += $self->getCustomButtonSize( $buttonId ) if defined $buttonId; } Logging::debug("Domain '$domain': ". (caller(0))[3]." finished. Size is $size bytes."); return $size; } sub getDomainDbSize { my ($self, $domain, $domainId ) = @_; my $size = 0; Logging::debug("Domain '$domain': ". (caller(0))[3]." started."); my $sql = "SELECT dbases FROM disk_usage WHERE dom_id=$domainId"; if ( $self->{dbh}->execute_rownum($sql) and my $ptrRow = $self->{dbh}->fetchrow() ) { $size += $ptrRow->[0]; } $self->{dbh}->finish(); Logging::debug("Domain '$domain': ". (caller(0))[3]." finished. Size is $size bytes."); return $size; } sub getDomainPhostingSize{ my ($self, $domain, $domainId, $domainAsciiName ) = @_; my $size = 0; Logging::debug("Domain '$domain': ". (caller(0))[3]." started."); my $webspaceRoot = $self->getWebspaceRoot($domainAsciiName); $size += $self->getCidSize($webspaceRoot); my $domainRoot = $self->getDomainRoot($domainAsciiName); $size += $self->getDomainAnonFtpSize($domain, $domainId, $domainAsciiName); Logging::debug("Domain '$domain': ". (caller(0))[3]." finished. Size is $size bytes."); return $size; } sub getDomainAnonFtpSize { my ($self, $domain, $domainId, $domainAsciiName ) = @_; my $size = 0; Logging::debug("Domain '$domain': ". (caller(0))[3]." started."); my $sql = "SELECT * FROM anon_ftp WHERE dom_id=$domainId"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( my $ptrHash = $self->{dbh}->fetchhash() ) { my $domainRoot = $self->getDomainRoot($domainAsciiName); if ( -d $domainRoot ) { my $pub_path = "$domainRoot/anon_ftp/pub"; my $incoming_path = "$domainRoot/anon_ftp/incoming"; $size += $self->getCidSize($pub_path); $size += $self->getCidSize($incoming_path); } } } $self->{dbh}->finish(); Logging::debug("Domain '$domain': ". (caller(0))[3]." finished. Size is $size bytes."); return $size; } sub getDomainTomcatSize{ my ($self, $domain, $domainId, $domainAsciiName ) = @_; my $size = 0; Logging::debug("Domain '$domain': ". (caller(0))[3]." started."); if ( PleskVersion::atLeast( 6, 0, 0 ) ) { my $tomcatServiceStatus = $self->getDomainServiceStatus( $domainId, 'tomcat' ); if (defined $tomcatServiceStatus) { my $sql = "SELECT wa.name FROM WebApps wa LEFT JOIN DomainServices ds ON wa.domain_service_id=ds.id WHERE ds.dom_id = $domainId"; my ( @webapps ); if ( $self->{dbh}->execute_rownum($sql) ) { while ( my $ptrRow = $self->{dbh}->fetchrow() ) { push (@webapps, $ptrRow->[0] ); } } $self->{dbh}->finish(); my $warDir = AgentConfig::get("CATALINA_HOME") . "/psa-wars/$domainAsciiName"; foreach my $webapp ( @webapps ) { $size += $self->getCidSize("$warDir/$webapp.war"); } } } Logging::debug("Domain '$domain': ". (caller(0))[3]." finished. Size is $size bytes."); return $size; } sub getDomainMailSize{ my ($self, $domain, $domainAsciiName, $domainId ) = @_; my $size = 0; Logging::debug("Domain '$domain': ". (caller(0))[3]." started."); my $mailNamesPath = getPleskMailnamesDir() . "/$domainAsciiName/"; # inclides mailboxes, attachments and spamassassin content if ( -e $mailNamesPath ) { $size += $self->getCidSize($mailNamesPath); } if ( PleskVersion::atLeast( 7, 1, 0 ) ) { my ( @mailIds ); my $sql = "SELECT id FROM mail WHERE dom_id = $domainId"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( my $ptrRow = $self->{dbh}->fetchrow() ) { push (@mailIds, $ptrRow->[0]); } } $self->{dbh}->finish(); } Logging::debug("Domain '$domain': ". (caller(0))[3]." finished. Size is $size bytes."); return $size; } sub getDomainMaillistsSize { my ($self, $domain, $domainId ) = @_; my $size = 0; Logging::debug("Domain '$domain': ". (caller(0))[3]." started."); if ( PleskVersion::atLeast( 6, 0, 0 ) ) { my $archiveDir = AgentConfig::get("MAILMAN_VAR_D") . "/archives/private"; my $sql = "SELECT id,name,status FROM MailLists WHERE dom_id=$domainId"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( my $ptrRow = $self->{dbh}->fetchrow() ) { my $datafile = $archiveDir . "/" . $ptrRow->[1] . ".mbox/" . $ptrRow->[1] . ".mbox"; if ( -f $datafile ) { $size += $self->getCidSize($datafile); } else { Logging::debug("file '$datafile' doesn't exist" ); } } } $self->{dbh}->finish(); } Logging::debug("Domain '$domain': ". (caller(0))[3]." finished. Size is $size bytes."); return $size; } sub getClientBackupSize { my ($self, $client ) = @_; my $size = 0; Logging::info("Get backup size for client '$client'"); if ( $self->{configuration_dump} ) { Logging::info("Get backup size for client '$client' finished. Configuration-only mode detected. Size is $size bytes."); return 0; } my $clientId = PleskStructure::getClientId($client); if ( not defined $clientId ) { Logging::error("Failed to get client id for '$client'"); return 0; } if ( !$self->{only_mail_dump} and PleskVersion::atLeast( 6, 0, 0 ) ) { $size += $self->getClientSkeletonSize($client, $clientId); } if ( !$self->{only_mail_dump} and PleskVersion::atLeast( 7, 1, 0 ) ) { $size += $self->getClientCustomButtonsSize($client, $clientId); } Logging::info("Get backup size for client '$client' finished. Size is $size bytes."); return $size; } sub getClientSkeletonSize { my ($self, $client, $clientId ) = @_; my $size = 0; Logging::debug("Client '$client': ". (caller(0))[3]." started."); my $skeletonPath = AgentConfig::get('HTTPD_VHOSTS_D') . "/.skel/$clientId"; if ( -e $skeletonPath ) { $size += $self->getCidSize($skeletonPath); } Logging::debug("Client '$client': ". (caller(0))[3]." finished. Size is $size bytes."); return $size; } sub getClientCustomButtonsSize { my ($self, $client, $clientId ) = @_; my $size = 0; Logging::debug("Client '$client': ". (caller(0))[3]." started."); my @buttonIds = $self->getCustomButtonIdsByOwner71('client', $clientId); foreach my $buttonId ( @buttonIds ) { $size += $self->getCustomButtonSize( $buttonId ) if defined $buttonId; } Logging::debug("Client '$client': ". (caller(0))[3]." finished. Size is $size bytes."); return $size; } sub getServerSettingsBackupSize { my ($self) = @_; my $size = 0; Logging::info("Get backup size for server settings"); if ( $self->{configuration_dump} ) { Logging::info("Get backup size for server settings finished. Configuration-only mode detected. Size is $size bytes."); return 0; } my $skeletonPath = AgentConfig::get('HTTPD_VHOSTS_D') . "/.skel/0"; $size += $self->getCidSize($skeletonPath); $size += $self->getServerSettingsKeysSize(); $size += $self->getServerSettingsAppPackagesSize(); $size += $self->getServerCustomButtonsSize(); Logging::info("Get backup size of server settings finished. Size is $size bytes."); return $size; } sub getServerSettingsAppPackagesSize { my ($self) = @_; my $size = 0; Logging::debug("Server: ". (caller(0))[3]." started."); if ( PleskVersion::atLeast( 8, 3, 0 ) ) { my $distrib_path = AgentConfig::get("PRODUCT_ROOT_D") . "/var/apspkgarc"; my %mapHash = $self->parseApsIndexFile( $distrib_path . "/archive-index.xml" ); my $sql = "SELECT `name`, `version`, `release` FROM SiteAppPackages"; if( $self->{dbh}->execute_rownum($sql) ) { while ( my $ptrRow = $self->{dbh}->fetchrow() ) { my $distrib_name = $ptrRow->[0] . "-" . $ptrRow->[1] . "-" . $ptrRow->[2]; my $file_name; foreach my $tfile_name ( keys %mapHash ) { if ( $distrib_name eq join( "-", @{ $mapHash{$tfile_name} } ) ) { $file_name = $tfile_name; } } $size += $self->getCidSize("$distrib_path/$file_name"); } } $self->{dbh}->finish(); } Logging::debug("Server: ". (caller(0))[3]." finished. Size is $size bytes."); return $size; } sub getServerSettingsKeysSize { my ($self) = @_; my $size = 0; Logging::debug("Server: ". (caller(0))[3]." started."); if ( PleskVersion::atLeast( 9, 0, 0 ) ) { my $phpini = AgentConfig::get('PRODUCT_ROOT_D') . "/admin/conf/php.ini"; my $swkeyrepo = '/etc/sw/keys'; if( -e $phpini ){ open PHPINI, $phpini; while () { chomp; next if /^#/; next if /^$/; if ( $_ =~ /swkey\.repository_dir\s*=\s*[\"\']?(.+)[\"\']\s*$/) { $swkeyrepo = $1; Logging::debug( "getServerSettingsBackupSize: Found sw key repository: $swkeyrepo" ); last; } } close PHPINI; } if( -d "$swkeyrepo/keys" ){ my $keyDir = "$swkeyrepo/keys"; Logging::debug( "getServerSettingsBackupSize: Load keys from '$keyDir'" ); opendir DIR, "$keyDir"; my @files = readdir( DIR ); closedir DIR; foreach my $key(@files) { if( $key ne '.' and $key ne '..' and -f "$keyDir/$key" ){ $size += $self->getCidSize("$keyDir/$key"); } } } else{ Logging::debug( "getServerSettingsBackupSize: Keys directory '$swkeyrepo/keys' is not found. The keys are not included to backup." ); } } else{ my $sql = "SELECT * FROM key_history WHERE filename IS NOT NULL"; if($self->{dbh}->execute_rownum($sql)) { while ( my $ptrHash = $self->{dbh}->fetchhash() ) { next if ( $ptrHash->{'filename'} =~ /\~$/ ); my @keyPath = split( /\//, $ptrHash->{'filename'} ); my ( $keyName, $keyDir, $additional ); if ( $keyPath[3] eq 'key.d' ) { $keyName = $keyPath[4]; $keyDir = "/etc/psa/key.d/"; $additional = "true"; } else { $keyName = $keyPath[3]; $keyDir = "/etc/psa/"; $additional = "false"; } if ( -e $keyDir . "/" . $keyName ) { $size += $self->getCidSize("$keyDir/$keyName"); } } } $self->{dbh}->finish(); } Logging::debug("Server: ". (caller(0))[3]." finished. Size is $size bytes."); return $size; } sub getServerCustomButtonsSize { my ($self) = @_; my $size = 0; Logging::debug("Server: ". (caller(0))[3]." started."); my @buttonIds = $self->getCustomButtonIdsByOwner71('server', 0); foreach my $buttonId ( @buttonIds ) { $size += $self->getCustomButtonSize( $buttonId ) if defined $buttonId; } Logging::debug("Server: ". (caller(0))[3]." finished. Size is $size bytes."); return $size; } sub getCustomButtonSize { my ($self, $id) = @_; my $size = 0; my $customButtonsDir = AgentConfig::get("PRODUCT_ROOT_D") . '/admin/htdocs/images/custom_buttons'; my $sql = "SELECT file FROM custom_buttons WHERE id=$id AND place!=''"; if ( $self->{dbh}->execute_rownum($sql) and my $ptrRow = $self->{dbh}->fetchrow() ) { my $file = $ptrRow->[0]; if ( $file ) { $size += $self->getCidSize("$customButtonsDir/$file"); } } $self->{dbh}->finish(); return $size; } sub getCidSize { my ($self, $path, $no_recursion) = @_; my $cmd = "du -sb"; if ( defined $no_recursion ) { $cmd .= " -S"; } $cmd .= " $path"; my $sizes = `$cmd`; my $unpacksize = 0; for(split /[\r\n]+/,$sizes) { my ($number, $file) = split /\t/,$_,2; $unpacksize += $number; } Logging::debug("Retrieve size of '$path'" . ($no_recursion? "without recursion" : "" ) . ": $unpacksize bytes" ); return $unpacksize; } sub writeStatistics { my $self = shift; my $logPath = $ENV{'COLLECT_BACKUP_STAT_LOG'}; if (!defined($logPath) || length($logPath) == 0) { $logPath = "perfomance-statistics.log"; } $logPath = ">>" . $logPath; open(LOGFILE, $logPath); print $logPath; print LOGFILE "Date: " . $self->getTime() . "\n"; my $allTime = $self->{stopWatch}->getDiff("all"); print LOGFILE "All time: " . $allTime . "\n"; print LOGFILE "Sql time: " . $self->{dbh}->getStatistics()->{sqlTime} . "\n"; my $xmlTarTime = $self->{packer}->getStatistics()->{totalTime}; my $tarTime = $self->{packer}->getStatistics()->{tarTime}; print LOGFILE "Xml time: " . ($xmlTarTime - $tarTime) . "\n"; print LOGFILE "Files time: " . $tarTime . "\n"; print LOGFILE "\n"; close(LOGFILE); } sub getTime { my $self = shift; my ($second, $minute, $hour, $day, $month, $year) = localtime(time); $year+=1900; $second = "0".$second if length($second) < 2; $minute = "0".$minute if length($minute) < 2; $hour = "0".$hour if length($hour) < 2; $day = "0".$day if length($day) < 2; $month++; $month = "0".$month if length($month) < 2; return "$year.$month.$day $hour:$minute:$second"; } # --- Utility methods --- sub getPostgresqlVersion { my $psql = AgentConfig::psqlBin(); my @out = `$psql --version | awk '{print \$3}'`; chomp $out[0]; if ( $out[0] =~ /(\d+\.\d+\.\d+).*/ ) { return $1; } } sub getPleskMailnamesDir{ return AgentConfig::get('PLESK_MAILNAMES_D') if PleskVersion::atLeast( 9, 0, 0 ); return AgentConfig::get('QMAIL_MAILNAMES_D'); } # Returns the elements that present in first array, but not in the second. # Arrays must be sorted. # Linear complexity. sub arrayDifference { my ( $a1, $a2 ) = @_; my @ret; my $i1 = 0; my $i2 = 0; while ( $i1 < scalar(@$a1) && $i2 < scalar(@$a2) ) { if ( $a1->[$i1] eq $a2->[$i2] ) { $i1++; $i2++; next; } if ( $a1->[$i1] lt $a2->[$i2] ) { push @ret, $a1->[$i1]; $i1++; next; } if ( $a1->[$i1] gt $a2->[$i2] ) { $i2++; next; } } while ( $i1 < scalar(@$a1) ) { push @ret, $a1->[$i1]; $i1++; } return @ret; } # Returns the elements that present in both arrays # Arrays must be storted # Linear complexity sub arrayIntersection { my ( $a1, $a2 ) = @_; my @ret; my $i1 = 0; my $i2 = 0; while ( $i1 < scalar(@$a1) && $i2 < scalar(@$a2) ) { if ( $a1->[$i1] eq $a2->[$i2] ) { push @ret, $a1->[$i1]; $i1++; $i2++; next; } if ( $a1->[$i1] lt $a2->[$i2] ) { $i1++; next; } if ( $a1->[$i1] gt $a2->[$i2] ) { $i2++; next; } } return @ret; } # --- Private instance methods --- # # maps to translate xmlName => fieldName # my %xmlPermissions = ( 'create_domains' => 1, 'manage_phosting' => 1, 'manage_php_safe_mode' => 1, 'manage_quota' => 1, 'manage_subdomains' => 1, 'manage_dns' => 1, 'manage_log' => 1, 'manage_crontab' => 1, 'manage_anonftp' => 1, 'manage_webapps' => 1, 'manage_sh_access' => 1, 'manage_maillists' => 1, 'make_dumps' => 1, 'allow_local_backups' => 1, 'allow_ftp_backups' => 1, 'make_phosting' => 1, 'manage_quota' => 1, 'manage_not_chroot_shell' => 1, 'manage_ftp_password' => 1, 'cp_access' => 1, 'remote_access_interface' => 1, 'manage_domain_aliases' => 1, 'manage_virusfilter' => 1, 'manage_spamfilter' => 1, 'manage_webstat' => 1, 'manage_performance' => 1, 'allow_oversell' => 1, 'create_clients' => 1, 'select_db_server' => 1, 'manage_subftp' => 1, 'access_appcatalog' => 1, 'allow_insecure_sites' => 1, 'site_builder' => 1, ); my %commonLimits = ( 'max_wu' => 1, 'max_db' => 1, 'max_pbox' => 1, 'mbox_quota' => 1, 'disk_space' => 1, 'max_traffic' => 1, 'max_subftp_users' => 1, 'max_unity_mobile_sites' => 1, ); my %domainLimits25 = %commonLimits; $domainLimits25{'max_box'} = 1; my %domainLimits = %commonLimits; $domainLimits{'max_box'} = 1; $domainLimits{'expiration'} = 1; $domainLimits{'max_subdom'} = 1; $domainLimits{'max_maillists'} = 1; $domainLimits{'max_webapps'} = 1; $domainLimits{'max_dom_aliases'} = 1; $domainLimits{'disk_space_soft'} = 1; $domainLimits{'max_traffic_soft'} = 1; $domainLimits{'max_site'} = 1; $domainLimits{'max_site_builder'} = 1; my %clientLimits25 = %domainLimits25; $clientLimits25{'max_dom'} = 1; my %clientLimits = %domainLimits; $clientLimits{'max_dom'} = 1; delete $clientLimits{'max_site'}; #PSA 9.0 my %resellerLimits = %clientLimits; $resellerLimits{'max_cl'} = 1; my %typeOfField = ( 'expiration' => 'timestamp' ); my %hostingScripting = ( 'ssi' => 'ssi', 'php' => 'php', 'php_safe_mode' => 'php_safe_mode', 'cgi' => 'cgi', 'perl' => 'perl', 'asp' => 'asp', 'python' => 'python', 'coldfusion' => 'coldfusion', 'asp_dot_net' => 'asp_dot_net', 'fastcgi' => 'fastcgi', 'miva' => 'miva', 'php_handler_type' => 'php_handler_type' ); my %subDomainScripting = ( 'ssi' => 'ssi', 'php' => 'php', 'cgi' => 'cgi', 'perl' => 'perl', 'asp' => 'asp', 'python' => 'python', 'coldfusion' => 'coldfusion', 'asp_dot_net' => 'asp_dot_net', 'fastcgi' => 'fastcgi', 'miva' => 'miva', 'php_handler_type' => 'php_handler_type' ); my %emptyableBoolElementInTemplate = ( 'asp' => 1, 'cgi' => 1, 'coldfusion' => 1, 'pdir_plesk_stat' => 1, 'perl' => 1, 'php' => 1, 'python' => 1, 'ssi' => 1 ); my %custom_button_owner_types = ( "admin" => 1, #IS_ADMIN "server" => 1, #IS_ADMIN "reseller" => 2, #IS_RESELLER "client" => 4, #IS_CLIENT "domain-admin" => 8, #IS_DOMAIN_OWNER "mailuser" => 16, #IS_MAIL_USER ); my %locale_map = ( 'bg' => 'bg', 'hk' => 'zh-HK', 'ru' => 'ru-RU', 'en' => 'en-US', 'nl' => 'nl-NL', 'br' => 'pt-BR', 'it' => 'it-IT', 'tr' => 'tr-TR', 'es' => 'es-ES', 'pl' => 'pl-PL', 'ca' => 'ca-ES', 'jp' => 'ja-JP', 'tw' => 'zh-TW', 'fi' => 'fi-FI', 'cn' => 'zh-CN', 'ko' => 'ko-KR', 'fr' => 'fr-FR', 'pt' => 'pt-PT', 'de' => 'de-DE', 'lt' => 'lt-LT' ); my %rlocale_map = reverse %locale_map; # list of attributes for template-item node in dump.xml # needs to synchronize with template-item's ATTLIST of plesk.dtd my %template_items = ( 'webmail' => 1, 'disk_space' => 1, 'disk_space_soft' => 1, 'stat_ttl' => 1, 'maillists' => 1, 'wu_script' => 1, 'max_traffic' => 1, 'max_traffic_soft' => 1, 'max_box' => 1, 'mbox_quota' => 1, 'max_wu' => 1, 'max_db' => 1, 'max_maillists' => 1, 'max_webapps' => 1, 'max_subdom' => 1, 'max_site' => 1, 'max_dom_aliases' => 1, 'expiration' => 1, 'max_subftp_users'=> 1, 'vh_type' => 1, 'quota' => 1, 'ssl' => 1, 'same_ssl' => 1, 'fp' => 1, 'fp_ssl' => 1, 'fp_auth' => 1, 'asp' => 1, 'ssi' => 1, 'php' => 1, 'cgi' => 1, 'perl' => 1, 'python' => 1, 'fastcgi' => 1, 'coldfusion' => 1, 'webstat' => 1, 'errdocs' => 1, 'shell' => 1, 'pdir_plesk_stat' => 1, 'dns_type' => 1, 'php_handler_type'=> 1, 'php_safe_mode' => 1, 'max_connections' => 1, 'bandwidth' => 1, 'miva' => 1, 'sb_publish' => 1, 'nonexist_mail' => 1, 'catch_addr' => 1, 'bounce_mess' => 1, 'max_site_builder' => 1, 'max_unity_mobile_sites' => 1, 'upsell_site_builder' => 1, # client template 'cp_access' => 1, 'create_domains' => 1, 'manage_phosting' => 1, 'manage_php_safe_mode' => 1, 'manage_quota' => 1, 'manage_dns' => 1, 'manage_log' => 1, 'manage_crontab' => 1, 'manage_anonftp' => 1, 'manage_webapps' => 1, 'manage_maillists' => 1, 'manage_sh_access' => 1, 'manage_not_chroot_shell' => 1, 'manage_subdomains' => 1, 'manage_virusfilter' => 1, 'manage_drweb' => 1, 'allow_local_backups' => 1, 'allow_ftp_backups' => 1, 'remote_access_interface' => 1, 'manage_domain_aliases' => 1, 'manage_spamfilter' => 1, 'manage_webstat' => 1, 'manage_performance' => 1, 'select_db_server' => 1, 'manage_subftp' => 1, 'access_appcatalog' => 1, 'allow_insecure_sites' => 1, 'excl_ip_num' => 1, 'max_dom' => 1, #reseller 'create_clients' => 1, 'allow_oversell' => 1, 'oversell' => 1, #overselling 'overuse' => 1, 'max_cl' => 1, #server 'shared' => 1 ); my %template_items_ignore_addon = ( 'cp_access' => 1, 'remote_access_interface' => 1, 'disk_space_soft' => 1, 'max_traffic_soft' => 1, 'stat_ttl' => 1, 'maillists' => 1, 'overuse' => 1, 'dns_type' => 1, 'nonexist_mail' => 1 ); my %defaultClientPermissions = ( "allow_ftp_backups" => "false" , "allow_local_backups" => "false" , "change_limits" => "false" , "cp_access" => "true" , "create_domains" => "false" , "dashboard" => "true" , "manage_anonftp" => "false" , "manage_crontab" => "false" , "manage_dashboard" => "true" , "manage_dns" => "false" , "manage_domain_aliases" => "false" , "manage_log" => "false" , "manage_maillists" => "false" , "manage_not_chroot_shell" => "false" , "manage_performance" => "false" , "manage_phosting" => "false" , "manage_php_safe_mode" => "false" , "manage_quota" => "false" , "manage_sh_access" => "false" , "manage_spamfilter" => "false" , "manage_subdomains" => "false" , "manage_virusfilter" => "false" , "manage_webapps" => "false" , "manage_webstat" => "true" , "remote_access_interface" => "false" , "select_db_server" => "false" , "stdgui" => "true" ); my %defaultDomainPermissions = ( "allow_ftp_backups" => "false" , "allow_local_backups" => "false" , "cp_access" => "true" , "create_domains" => "false" , "manage_anonftp" => "false" , "manage_crontab" => "false" , "manage_dns" => "false" , "manage_domain_aliases" => "false" , "manage_log" => "false" , "manage_maillists" => "false" , "manage_not_chroot_shell" => "false" , "manage_performance" => "false" , "manage_phosting" => "false" , "manage_php_safe_mode" => "false" , "manage_quota" => "false" , "manage_sh_access" => "false" , "manage_spamfilter" => "false" , "manage_subdomains" => "false" , "manage_virusfilter" => "false" , "manage_webapps" => "false" , "manage_webstat" => "true" , "remote_access_interface" => "false" , "select_db_server" => "false" ); # # end maps # sub filterSelectedResellers{ my( $self, $input ) = @_; my @ret = @{$input}; @ret = arrayIntersection( \@ret, $self->{resellers} ) if exists $self->{resellers}; @ret = arrayDifference( \@ret, $self->{exclude_resellers} ) if exists $self->{exclude_resellers}; return @ret; } sub filterSelectedClients{ my( $self, $input ) = @_; my @ret = @{$input}; @ret = arrayIntersection( \@ret, $self->{clients} ) if exists $self->{clients}; @ret = arrayDifference( \@ret, $self->{exclude_clients} ) if exists $self->{exclude_clients}; return @ret; } sub filterSelectedDomains{ my( $self, $input ) = @_; my @ret = @{$input}; @ret = arrayIntersection( \@ret, $self->{domains} ) if exists $self->{domains}; @ret = arrayDifference( \@ret, $self->{exclude_domains} ) if exists $self->{exclude_domains}; return @ret; } sub getAdminRootPath{ my ($self) = @_; $self->{packer}->regAdminObjectBackupPath( '' ); } sub createFullDump { my ($self) = @_; $self->getAdminRootPath(); my $adminId = PleskStructure::getAdminId(); $self->{packer}->addRootAdmin( $adminId, PleskStructure::getAdminGuid() ); $self->{dump_status}->start(PleskStructure::getClientsCount(''), PleskStructure::getDomainsCount( '' ) ); my @resellers = sort { $a cmp $b } PleskStructure::getResellers(); @resellers = $self->filterSelectedResellers( \@resellers ); foreach my $reseller (@resellers) { my @myclients = sort { $a cmp $b } PleskStructure::getMyClients($reseller); @myclients = $self->filterSelectedClients( \@myclients ); my @domains = sort { $a cmp $b } PleskStructure::getDomainsForClient($reseller); @domains = $self->filterSelectedDomains( \@domains ); $self->makeClientNode($reseller, \@domains, \@myclients, 0 ); } my @clients = sort { $a cmp $b } PleskStructure::getAdminClients(); foreach my $client (@clients) { if( PleskStructure::getClientType( $client ) eq 'client' ){ my @myclients = sort { $a cmp $b } PleskStructure::getMyClients($client); @myclients = $self->filterSelectedClients( \@myclients ); my @domains = sort { $a cmp $b } PleskStructure::getDomainsForClient($client); @domains = $self->filterSelectedDomains( \@domains ); $self->makeClientNode($client, \@domains, \@myclients, 0 ); } } my $adminName = PleskStructure::getAdminName(); $self->{dump_status}->startClient($adminName); my @adminDomains = PleskStructure::getAdminDomains(); @adminDomains = $self->filterSelectedDomains( \@adminDomains ); foreach my $domainName(@adminDomains) { $self->makeDomainNode($domainName, 0 ); } for my $userLogin (PleskStructure::getUserLogins($adminName) ) { my $userHash = $self->getUserHash($userLogin); $self->{packer}->addAdminUser($userLogin, $userHash); } for my $roleId (PleskStructure::getRoleIds($adminName) ) { my %permissions = $self->getRolePermissions($roleId); my $sql = "SELECT name FROM smb_roles WHERE id = '$roleId' and isBuiltIn = 0"; if ( $self->{dbh}->execute_rownum($sql) ) { if ( my $ptrHash = $self->{dbh}->fetchhash() ) { $self->{packer}->addAdminRole($ptrHash->{'name'}, 0, \%permissions); } } $self->{dbh}->finish(); } $self->{dump_status}->endClient($adminName); $self->{dump_status}->finishObjects(); } sub getClientRootPath{ my ($self, $clientLogin ) = @_; my $clientId = PleskStructure::getClientId($clientLogin); my $clientType = PleskStructure::getClientType($clientLogin); if( $clientType eq 'reseller' ){ return $self->{packer}->regResellersObjectBackupPath( $self->getAdminRootPath(), $clientId, $clientLogin ); } elsif( $clientType eq 'client' ){ if ( PleskVersion::atLeast( 9, 0, 0 ) ) { my $parentId = PleskStructure::getClientParentId( $clientLogin ); my $parentLogin = PleskStructure::getClientNameFromId( $parentId ); return $self->{packer}->regClientObjectBackupPath( $self->getClientRootPath($parentLogin), $clientId, $clientLogin ); } else{ return $self->{packer}->regClientObjectBackupPath( $self->getAdminRootPath(), $clientId, $clientLogin ); } } else{ return $self->getAdminRootPath(); } } sub beginWriteStatus{ my ($self) = @_; my %accounts; my %domains; if( exists $self->{resellers} ){ foreach my $reseller ( @{ $self->{resellers} } ) { $accounts{$reseller} = 1; my @myclients = sort { $a cmp $b } PleskStructure::getMyClients($reseller); @myclients = $self->filterSelectedClients( \@myclients ); for my $client( @myclients ){ $accounts{$client} = 1; } foreach my $client( @myclients ){ my @mydomains = sort { $a cmp $b } PleskStructure::getDomainsForClient($client); @mydomains = $self->filterSelectedDomains( \@mydomains ); for my $domain( @mydomains ){ $domains{$domain} = 1; } } } } if( exists $self->{clients} ){ foreach my $client ( @{ $self->{clients} } ) { $accounts{$client} = 1; my @mydomains = sort { $a cmp $b } PleskStructure::getDomainsForClient($client); @mydomains = $self->filterSelectedDomains( \@mydomains ); for my $domain( @mydomains ){ $domains{$domain} = 1; } } } if( exists $self->{domains} ){ for my $domain( @{$self->{domains}} ){ $domains{$domain} = 1; } } $self->{dump_status}->start( scalar( keys(%accounts) ), scalar( keys( %domains ) ) ); } sub createResellersDump{ my ($self) = @_; my( %clients, %domains ); my $client; foreach my $reseller ( @{ $self->{resellers} } ) { my @myclients = sort { $a cmp $b } PleskStructure::getMyClients($reseller); @myclients = $self->filterSelectedClients( \@myclients ); $clients{$reseller} = \@myclients; my @mydomains = sort { $a cmp $b } PleskStructure::getDomainsForClient($reseller); @mydomains = $self->filterSelectedDomains( \@mydomains ); $domains{$reseller} = \@mydomains; } foreach my $reseller ( @{ $self->{resellers} } ) { $self->getClientRootPath( $reseller ); $self->makeClientNode($reseller, $domains{$reseller}, $clients{$reseller}, 1 ); } } # $clients - ref to the hash clientNames to ref of array of domainNames sub createClientsDump { my ( $self ) = @_; my $client; my (%clients); foreach my $client ( @{ $self->{clients} } ) { my @mydomains = sort { $a cmp $b } PleskStructure::getDomainsForClient($client); @mydomains = $self->filterSelectedDomains( \@mydomains ); $clients{$client} = \@mydomains; } foreach $client (keys %clients) { $self->getClientRootPath( $client ); $self->makeClientNode($client,$clients{$client}, undef, 1 ); } } sub getDomainRootPath{ my ($self, $domainName ) = @_; my $domainNameColumn = 'name'; if ( PleskVersion::atLeast( 7, 1, 0 ) ) { $domainNameColumn = 'displayName'; } my $sql = "SELECT id, cl_id, name FROM domains WHERE $domainNameColumn = '$domainName'"; my $ptrHash; my $domainId; my $clientId; my $domainAscName; if( $self->{dbh}->execute($sql) ) { if ( $ptrHash = $self->{dbh}->fetchhash() ) { $domainId = $ptrHash->{'id'}; $clientId = $ptrHash->{'cl_id'}; $domainAscName = $ptrHash->{'name'}; } } $self->{dbh}->finish(); if ( defined $domainId and defined $clientId and defined $domainAscName) { return $self->{packer}->regDomainObjectBackupPath( $self->getClientRootPath( PleskStructure::getClientNameFromId( $clientId ) ), $domainId, $domainAscName ); } } # $domains - ref to the array of domain names sub createDomainsDump { my ( $self ) = @_; my $domain; foreach $domain ( @{$self->{domains}} ) { if ( $self->getDomainRootPath( $domain ) ) { $self->makeDomainNode( $domain, 1 ); } else { my $msg = "Unable to backup domain because of unappropriate database content"; print STDERR "$msg\n"; Packer::printToError( $msg ); } } } # Condition is not necessary if getting admin parameters sub getMaxButtonLength { my ( $self, $parent, $parentType, $table, $condition, $tableValues ) = @_; my $value; if( ref($tableValues) eq 'HASH' ){ $value = $tableValues->{'max_button_length'} if exists $tableValues->{'max_button_length'}; } else{ my $sql = "SELECT val FROM $table WHERE param='max_button_length'"; $sql .= " AND $condition" if $condition; if ( $self->{dbh}->execute_rownum($sql) and my $ptrRow = $self->{dbh}->fetchrow() ){ $value = $ptrRow->[0]; } $self->{dbh}->finish(); } if ( $value ){ my $proc = undef; if ( $parentType eq 'client' ) { $proc = $self->getSubroutineRef("setClientMaxButtonLength"); } else { Packer::printToError( "Error: getMaxButtonLength: Unexpected type of parent \"$parentType\"" ); return; } if ($proc) { $self->{packer}->$proc( $parent, $value ); } } } #Condition is not necessary if getting admin parameters sub getSkin { my ( $self, $parent, $parentType, $table, $condition, $tableValues ) = @_; return unless PleskVersion::atLeast( 5, 0, 0 ); my $skinId = "skin_id"; my $value; if( ref($tableValues) eq 'HASH' ){ $value = $tableValues->{$skinId} if exists $tableValues->{$skinId}; if( $value ){ my $sql = "SELECT s.name FROM Skins as s WHERE s.id=$value"; if ( $self->{dbh}->execute_rownum($sql) and my $ptrRow = $self->{dbh}->fetchrow() ){ $value = $ptrRow->[0]; } $self->{dbh}->finish(); } } else{ my $sql = "SELECT s.name FROM Skins as s, $table as t " . "WHERE t.param='$skinId' AND t.val = s.id"; $sql .= " AND $condition" if $condition; if ( $self->{dbh}->execute_rownum($sql) and my $ptrRow = $self->{dbh}->fetchrow() ){ $value = $ptrRow->[0]; } $self->{dbh}->finish(); } if ( $value ){ my $proc = undef; if ( $parentType eq 'client' ) { $proc = $self->getSubroutineRef("setClientSkin"); } else { Packer::printToError( "Error: getSkin: Unexpected type of parent \"$parentType\""); return; } if ($proc) { $self->{packer}->$proc( $parent, $value ); } } } sub getLockScreen { my ( $self, $parent, $parentType, $table, $condition, $tableValues ) = @_; return unless PleskVersion::atLeast( 7, 5, 2 ); my $value; if( ref($tableValues) eq 'HASH' ){ $value = $tableValues->{'disable_lock_screen'} if exists $tableValues->{'disable_lock_screen'}; } else{ my $sql = "SELECT val FROM $table WHERE param='disable_lock_screen'"; $sql .= " AND $condition" if $condition; my $ptrRow; if ( $self->{dbh}->execute_rownum($sql) and $ptrRow = $self->{dbh}->fetchrow() ) { $value = $ptrRow->[0]; } $self->{dbh}->finish(); } if( $value and $value eq 'true' ) { my $proc = undef; if ( $parentType eq 'client' ) { $proc = $self->getSubroutineRef("setClientLockScreen"); } else { Packer::printToError( "Error: getLockSkreen: Unexpected type of parent \"$parentType\""); return; } if ($proc) { $self->{packer}->$proc($parent); } } } sub dumpDomainPersonalPermissions { my ( $self, $domainId, $permId ) = @_; $self->addPermissions( $domainId, 'domain-personal', $permId ); if ( !PleskVersion::atLeast( 7, 5, 4 ) ) { $self->{packer}->addDomainPersonalPermission( $domainId, 'manage_not_chroot_shell', 'true' ); } } # # sub makeClientNode # # arguments: # $clientId - ID of client # $full - dump all domains # $ptrDomainHash # sub makeClientNode { my ( $self, $clientName, $domains, $childClients, $isroot ) = @_; my ($parent, $clientType ); $clientType = PleskStructure::getClientType( $clientName ); if( $clientType eq 'client' and $self->clientExcluded( $clientName ) ) { Packer::printToLog("Client '$clientName' is excluded from dump"); return; } if( $clientType eq 'reseller' and $self->resellerExcluded( $clientName ) ) { Packer::printToLog("Reseller '$clientName' is excluded from dump"); return; } foreach my $dumpedClient( @{$self->{dumped_clients}} ){ if( $dumpedClient eq $clientName ){ Packer::printToLog("Client '$dumpedClient' already dumped"); return; } } push @{$self->{dumped_clients}}, $clientName; my ( $item, $sql, $ptrHash, $value, %client, $ptrRow, $id, %clientParams ); Packer::printToLog("Client '$clientName' is started") if $clientType eq 'client'; Packer::printToLog("Reseller '$clientName' is started") if $clientType eq 'reseller'; $self->{dump_status}->startClient($clientName); $sql = "SELECT * FROM clients WHERE login = '$clientName'"; if ( $self->{dbh}->execute($sql) ) { if (my $ptrHash = $self->{dbh}->fetchhash() ) { %client = %{ $ptrHash }; } } $self->{dbh}->finish(); my $clientId = $client{'id'}; $parent = PleskStructure::getClientNameFromId( $client{'parent_id'} ) if exists $client{'parent_id'}; if ( exists $client{'vendor_id'} ){ my $vendorGuid = PleskStructure::getClientGuidFromId( $client{'vendor_id'} ); $client{'vendor-guid'} = $vendorGuid; } $client{'country'} = $self->{packer}->normalizeCountry( $client{'country'} ); #FIX ME $root->setAttribute( 'parent-id', $parentName ); my %passwd; if ( PleskVersion::atLeast( 7, 1, 5 ) ) { $sql = "SELECT password, type FROM accounts WHERE id = '" . $client{'account_id'} . "'"; if ( $self->{dbh}->execute($sql) ) { if ( $ptrHash = $self->{dbh}->fetchhash() ) { %passwd = ( 'password' => $ptrHash->{'password'}, 'type' => $self->{packer}->normalizePasswordType( $ptrHash->{'type'} ) ); } else { %passwd = ( 'password' => '', 'type' => 'plain' ); my $msg = "Broken referencial integrity: Account password is not found for client " . $client{'account_id'}; print STDERR "$msg\n"; Packer::printToError( $msg ); } } $self->{dbh}->finish(); } else { %passwd = ( 'password' => $client{'passwd'}, 'type' => 'plain' ); } my $status = 0; if ( PleskVersion::atLeast( 5, 1, 0 ) ) { $status = $client{'status'}; } else { $status |= $Status::ADMIN if $client{'status'} eq 'false'; } my $doNotDumpDomainTemplates = 0; my $parentType; if( $parent ) { $parentType = PleskStructure::getClientType( $parent ); } else{ $parentType = 'admin'; } if( $clientType eq 'client' ){ if( $isroot ){ $self->{packer}->addRootClient( $clientId, \%client, \%passwd, $status, PleskStructure::getClientGuid( $parent ) ); } else{ if( $parentType eq 'admin' ) { $self->{packer}->addAdminClient( $clientId, \%client, \%passwd, $status ); } elsif( $parentType eq 'reseller' ) { $doNotDumpDomainTemplates = 1; $self->{packer}->addResellerClient($client{'parent_id'}, $clientId, \%client, \%passwd, $status ); } else{ die "Cannot dump client '$clientName' of type '$clientType', parent '$parent' type '$parentType' not supported!"; } } } elsif( $clientType eq 'reseller' ){ if( $isroot ){ $self->{packer}->addRootReseller( $clientId, \%client, \%passwd, $status ) } else{ if( $parentType eq 'admin' ) { $self->{packer}->addAdminReseller( $clientId, \%client, \%passwd, $status ); } else{ die "Cannot dump client '$clientName' of type '$clientType', parent '$parent' type '$parentType' not supported!"; } } } else{ die "Cannot dump client '$clientName'. unknown type '$clientType'!"; } unless ( $self->{shallow_dump} ) { $self->{packer}->setClientPinfo( $clientId, \%client ); # Locale changed format since 7.5.0, and we # don't bother converting older formats if ( PleskVersion::atLeast( 7, 5, 0 ) ) { if ( exists( $client{'locale'} ) && $client{'locale'} ) { $self->{packer}->setClientLocale( $clientId, $client{'locale'} ); } } $sql = "SELECT param,val FROM cl_param WHERE cl_id = $clientId"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( $ptrRow = $self->{dbh}->fetchrow() ) { $clientParams{ $ptrRow->[0] } = $ptrRow->[1]; } } $self->{dbh}->finish(); # button length $self->getMaxButtonLength( $clientId, 'client', "cl_param", "cl_id=$clientId", \%clientParams ); $self->getSkin( $clientId, 'client', "cl_param", "cl_id=$clientId", \%clientParams ); $self->getLockScreen( $clientId, 'client', "cl_param", "cl_id=$clientId", \%clientParams ); if (PleskVersion::atLeast( 10, 0, 0) and not PleskVersion::isSmb()) { $self->{packer}->addClientGappsAccount($clientId, \%clientParams); } # # limits # if ( PleskVersion::atLeast( 6, 0, 0 ) ) { if( $clientType eq 'reseller' ) { $self->addResellerLimits( $clientId, $client{'limits_id'} ) ; $self->addOverusePolicy( 'client', $clientId, \%clientParams ); } else{ if (!PleskVersion::atLeast( 10, 0, 0)) { $self->addClientLimits( $clientId, $client{'limits_id'} ) ; $self->addOverusePolicy( 'client', $clientId, \%clientParams ); } } } elsif ( PleskVersion::atLeast( 5, 0, 0 ) ) { $self->addClientLimits( $clientId, $clientParams{'lim_id'} ); } else { $self->addClientLimits25( $clientId, $clientParams{'lim_id'} ); } $self->{packer}->fixDefaultLimits($clientType,$clientId); # # end limits # if ( PleskVersion::atLeast( 6, 0, 0 ) ) { $self->addPermissions( $clientId, 'client', $client{'perm_id'} ); } elsif ( PleskVersion::atLeast( 5, 0, 0 ) ) { $self->addPermissions( $clientId, 'client', $clientParams{'perm_id'} ); } else { $self->addPermissions25($clientId); } #fix bug 88139 if ( ( PleskVersion::atLeast( 7, 5, 1 ) and !$client{'perm_id'} ) or !PleskVersion::atLeast( 7, 5, 1 ) ) { $self->{packer}->addClientPermission( $clientId, 'cp_access', 'true' ); } #fix bug 88544 if ( !PleskVersion::atLeast( 7, 5, 4 ) ) { $self->{packer}->addClientPermission( $clientId, 'manage_not_chroot_shell', 'true' ); } $self->addClientMulitpleLoginPermission($clientId, $clientParams{'multiply_login'} ) if exists $clientParams{'multiply_login'}; # # Domain skeleton # if ( PleskVersion::atLeast( 6, 0, 0 ) ) { my $skeletonPath = AgentConfig::get('HTTPD_VHOSTS_D') . "/.skel/$clientId"; if ( !$self->{configuration_dump} ) { $self->{packer}->addClientDomainSkeleton( $clientId, $skeletonPath, "skel" ); } } } my %ips = PleskStructure::getClientIps($clientName); $self->{packer}->addClientIps( $clientId, \%ips ); # Site Applications pool $self->dumpSiteAppPool($clientId); $self->addClientTraffic($clientId); unless ($doNotDumpDomainTemplates) { $self->dumpDomainTemplates( $clientId, $clientType ); } if( $childClients and @{$childClients} and @{$domains} ) { # we are in reseller node and should add nodes and before processing of domains, as this could lead to creating users and roles $self->{packer}->addResellerDomainsClientsNodes( $clientId ); } for my $domainName ( @{$domains} ) { $self->makeDomainNode( $domainName, 0 ); } # Make childs dump if( $childClients ){ foreach my $myClientName(@{$childClients}){ #TO DO check excluded clients. Not worked now my @clientdomains = PleskStructure::getDomainsForClient( $myClientName ); @clientdomains = sort { $a cmp $b } @clientdomains; @clientdomains = $self->filterSelectedDomains( \@clientdomains ); $self->makeClientNode($myClientName, \@clientdomains, undef, 0 ); } } for my $userLogin (PleskStructure::getUserLogins($clientName) ) { my $userHash = $self->getUserHash($userLogin); $self->{packer}->addClientUser($clientId, $userLogin, $userHash); } for my $roleId (PleskStructure::getRoleIds($clientName) ) { my %permissions = $self->getRolePermissions($roleId); my $sql = "SELECT name FROM smb_roles WHERE id = '$roleId' AND isBuiltIn = 0"; if ( $self->{dbh}->execute_rownum($sql) ) { if ( my $ptrHash = $self->{dbh}->fetchhash() ) { $self->{packer}->addClientRole($clientId, $ptrHash->{'name'}, 0, \%permissions); } } $self->{dbh}->finish(); } $self->getCustomButtonsByOwner( $clientType, $clientId ); if ( PleskVersion::atLeast( 10, 0, 0 ) and not PleskVersion::isSmb() ) { $self->getSubscription('client', $clientId); } if ( PleskVersion::atLeast( 8, 3, 0 ) ) { unless ( PleskVersion::atLeast( 10, 0, 0 ) and not PleskVersion::isSmb() ) { $self->makeClientSiteBuilderNode($clientId); } } if ( PleskVersion::atLeast( 10, 1, 0 ) and not PleskVersion::isSmb() ) { if ( $clientType eq 'reseller' ) { $self->{packer}->makeBrandingThemeNode($clientName, $clientId); } } if ( PleskVersion::atLeast( 10, 1, 0 ) and not PleskVersion::isSmb() ) { $self->dumpApsBundle($clientId, 'client'); } $self->{packer}->finishClient($clientId); $self->{dump_status}->endClient($clientName); } sub makeClientSiteBuilderNode () { my ( $self, $clientId ) = @_; my $sql = "SELECT sb_client_login, sb_reseller_id FROM SBResellers WHERE client_id='$clientId'"; my $enabled = 'false'; my @sbClients; if ( $self->{dbh}->execute_rownum($sql) ) { while ( my $ptrHash = $self->{dbh}->fetchhash() ) { push @sbClients, $ptrHash; $enabled = 'true'; } } $self->{packer}->setClientSiteBuilder( $clientId, \@sbClients, $enabled ); $self->{dbh}->finish(); } #----------------------------------------------------------------- # Dumps information about client's site applications pool #----------------------------------------------------------------- sub dumpSiteAppPool( $ $ ) { my ( $self, $cl_id ) = @_; # There were no commercial site applications prior to Plesk 7.1.0 if ( !PleskVersion::atLeast( 7, 1, 0 ) ) { return; } my $sql; my $aishared = "ai.shared"; if ( PleskVersion::atLeast( 9, 0, 0 ) ) { $aishared = "ai.disabled"; } if ( PleskVersion::atLeast( 8, 3, 0 ) ) { $sql = "SELECT sap.name AS sapp_name, sap.version AS sapp_version, sap.release AS sapp_release, lt.license_type_hash AS license_type_id, $aishared As SHARED, cai.instances_limit AS instances_limit " . "FROM APSClientApplicationItems AS cai " . "INNER JOIN APSApplicationItems AS ai ON (ai.id = cai.app_item_id AND cai.client_id = '$cl_id') " . "INNER JOIN SiteAppPackages AS sap ON (sap.id=ai.pkg_id) " . "LEFT JOIN APSLicenseTypes AS lt ON (ai.license_type_id = lt.id) AND $aishared = 'false'"; } elsif ( PleskVersion::atLeast( 7, 1, 0 ) ) { $sql ="SELECT sp.name AS sapp_name, sp.version AS sapp_version, sp.release AS sapp_release " . "FROM clients c INNER JOIN Repository r ON c.sapp_pool_id=r.rep_id " . "LEFT JOIN SiteAppPackages sp ON r.component_id=sp.id " . "WHERE c.id='$cl_id' AND (sp.access_level & 1) <> 0"; } if ( $self->{dbh}->execute_rownum($sql) ) { while ( my $ptrHash = $self->{dbh}->fetchhash() ) { $self->{packer}->addClientSapp( $cl_id, $ptrHash ); } } $self->{dbh}->finish(); } sub addPermissions25 { my ( $self, $parent, $parentType, $id ) = @_; # [42098] migration from 7.14 to 7.50 fails return unless ($id); my $proc = undef; if ( $parentType eq 'client' ) { $proc = $self->getSubroutineRef("addClientPermission"); } else { Packer::printToError( "Error: addPermissions25: Unexpected type of parent \"$parentType\""); return; } my ( $perm_name, $sql, $ptrRow, $value, $item ); my @perm_names = ( 'create_domains', 'manage_dns', 'manage_log' ); foreach $perm_name (@perm_names) { $sql = "SELECT DISTINCT val FROM cl_param WHERE cl_id = '$id' AND param = '$perm_name'"; if ( $self->{dbh}->execute_rownum($sql) ) { if ( $ptrRow = $self->{dbh}->fetchrow() ) { my $value = @{ $ptrRow }[0]; $self->{packer}->$proc( $parent, $perm_name, $value ); } } $self->{dbh}->finish(); } $sql = "SELECT DISTINCT val FROM cl_param WHERE cl_id='$id' AND (param='ip_based_allow' OR param='nb_allow')"; if ( $self->{dbh}->execute_rownum($sql) ) { if ( $ptrRow = $self->{dbh}->fetchrow() ) { my $value = @{ $ptrRow }[0]; $self->{packer}->$proc( $parent, 'manage_phosting', $value ); } } $self->{dbh}->finish(); } sub addOverusePolicy{ my( $self, $parentType, $parentId, $params ) = @_; my $proc; if ( $parentType eq 'client' ) { $proc = $self->getSubroutineRef( "addClientLimit" ); } elsif ( $parentType eq 'domain' ) { $proc = $self->getSubroutineRef( "addDomainLimit" ); } else { Packer::printToError( "Error: addOverusePolicy: Unexpected type of parent \"$parentType\""); return; } if( exists $params->{'DecompositionRule'} ){ if( $params->{'DecompositionRule'} eq 'oversell' ){ $self->{packer}->$proc( $parentId, 'oversell', 'true' ); } else{ $self->{packer}->$proc( $parentId, 'oversell', 'false' ); } } if( exists $params->{'OveruseBlock'} ){ if( $params->{'OveruseBlock'} eq 'true' ){ if ( exists $params->{'OveruseSuspend'}) { if ( $params->{'OveruseSuspend'} eq 'true') { $self->{packer}->$proc( $parentId, 'overuse', 'block' ); } else { $self->{packer}->$proc( $parentId, 'overuse', 'not_suspend' ); } } else { $self->{packer}->$proc( $parentId, 'overuse', 'not_suspend' ); } } elsif( $params->{'OveruseNotify'} eq 'true' ){ $self->{packer}->$proc( $parentId, 'overuse', 'notify' ); } else { $self->{packer}->$proc( $parentId, 'overuse', 'normal' ); } } else { $self->{packer}->$proc( $parentId, 'overuse', 'normal' ); } } sub addPermissions { my ( $self, $parent, $parentType, $id ) = @_; my $permsHash = $self->getPermsHash($id); unless ($permsHash) { if ( $parentType eq 'client' ) { $permsHash = $self->fillDefaultClientPermissions(); } else { $permsHash = $self->fillDefaultDomainPermissions(); } } return unless $permsHash; my $proc; if ( $parentType eq 'client' ) { $proc = $self->getSubroutineRef("addClientPermission"); } elsif ( $parentType eq 'domain-personal' ) { $proc = $self->getSubroutineRef("addDomainPersonalPermission"); } else { Packer::printToError( "Error: addPermissions: Unexpected type of parent \"$parentType\""); return; } foreach my $key ( keys %{$permsHash} ) { $self->{packer}->$proc( $parent, $key, $permsHash->{$key} ); } } sub getPermsHash { my ( $self, $permsId ) = @_; return unless $permsId; my ( $sql, $ptrRow, $item, $name, $value ); $sql = "SELECT permission,value FROM Permissions WHERE id=$permsId"; my %permsHash; if ( $self->{dbh}->execute_rownum($sql) ) { while ( $ptrRow = $self->{dbh}->fetchrow() ) { $name = $ptrRow->[0]; $value = $ptrRow->[1]; $name = "manage_virusfilter" if $name eq "manage_drweb"; next unless exists $xmlPermissions{$name}; if ( $name eq 'make_dumps' ) { $permsHash{'allow_local_backups'} = $value; $permsHash{'allow_ftp_backups'} = $value; next; } $permsHash{$name} = $value; } } $self->{dbh}->finish(); $sql = "SELECT value FROM Permissions WHERE id = $permsId and (" . "permission = 'ipb_allow' or permission = 'nb_allow')"; if ( $self->{dbh}->execute_rownum($sql) ) { if ( $ptrRow = $self->{dbh}->fetchrow() ) { my $value = @{ $ptrRow }[0]; $permsHash{'manage_phosting'} = $value; } } $self->{dbh}->finish(); return \%permsHash; } sub addClientMulitpleLoginPermission { my ( $self, $id, $multiple_sessions ) = @_; $self->{packer}->addClientPermission( $id, 'multiple-sessions', $multiple_sessions ); } sub insertLimit { my ( $self, $parent, $parentType, $name, $value ) = @_; my $proc; if ( $parentType eq 'client' || $parentType eq 'reseller' ) { $proc = $self->getSubroutineRef("addClientLimit"); } elsif ( $parentType eq 'domain' ) { $proc = $self->getSubroutineRef("addDomainLimit"); } else { Packer::printToError( "Error: insertLimits: Unexpected type of parent \"$parentType\""); return; } if ( $value eq '' || $value eq '-1' ) { $self->{packer}->$proc( $parent, $name, '-1' ); return; } if ( $name eq 'expiration' ) { my ( $mday, $mon, $year ) = ( localtime($value) )[ 3 .. 5 ]; $mon++; $year += 1900; $value = sprintf( '%04d-%02d-%02d', $year, $mon, $mday ); } if ( !PleskVersion::atLeast( 7, 0, 0 ) && $name eq 'mbox_quota' ) { $value = $value * 1024; } $self->{packer}->$proc( $parent, $name, $value ); } sub addResellerLimits { my ( $self, $resellerId, $limitsId ) = @_; return $self->addLimits( $resellerId, 'reseller', $limitsId, \%resellerLimits ); } sub addClientLimits { my ( $self, $clientId, $limitsId ) = @_; return $self->addLimits( $clientId, 'client', $limitsId, \%clientLimits ); } sub addClientLimits25 { my ( $self, $clientId, $limitsId ) = @_; return $self->addLimits25( $clientId, 'client', $limitsId, 'cl_id', 'cl_param' ); } sub addDomainLimits { my ( $self, $domainId, $limitsId ) = @_; return $self->addLimits( $domainId, 'domain', $limitsId, \%domainLimits ); } sub addDomainLimits25 { my ( $self, $domainId, $limitsId ) = @_; $self->addLimits25( $domainId, 'domain', $limitsId, 'dom_id', 'dom_param' ); #fix bug 50361 my $ptrRow; my $sql = "SELECT traffic FROM hosting WHERE dom_id='$domainId'"; if ( $self->{dbh}->execute_rownum($sql) && ( $ptrRow = $self->{dbh}->fetchrow() ) ) { $self->insertLimit( $domainId, 'domain', 'max_traffic', $ptrRow->[0] ); } $self->{dbh}->finish(); $sql = "SELECT size FROM domains WHERE id='$domainId'"; if ( $self->{dbh}->execute_rownum($sql) && ( $ptrRow = $self->{dbh}->fetchrow() ) ) { $self->insertLimit( $domainId, 'domain', 'disk_space', $ptrRow->[0] ); } $self->{dbh}->finish(); } sub addLimits25 { my ( $self, $parent, $parentType, $limitId, $limitNames, $idName, $paramName ) = @_; if ( !$limitId ) { return; } my ( $value, $name, $count, $sql, $ptrRow ); $sql = "SELECT val, param FROM $paramName WHERE $idName='$limitId'"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( $ptrRow = $self->{dbh}->fetchrow() ) { ( $name, $value ) = @{$ptrRow}; } } if ($limitNames) { foreach $name ( %{$limitNames} ) { $sql = "SELECT val FROM $paramName WHERE $idName = '$limitId' AND param = '$name'"; if ( ( $self->{dbh}->execute_rownum($sql) ) && ( $ptrRow = $self->{dbh}->fetchrow() ) ) { ($value) = @{$ptrRow}; if ( $name eq 'max_pbox' ) { $name = 'max_box'; } $self->insertLimit( $parent, $parentType, $name, $value ); } $self->{dbh}->finish(); } } } # # sub addLimits # # arguments: # $root - XML node to add 'limit' node # $limitID - limit id # # return: # $count - number of the added nodes # sub addLimits { my ( $self, $parent, $parentType, $limitId, $limitNames ) = @_; my $count = 0; if ( !$limitId ) { if ( $limitNames ) { foreach my $key ( keys %{$limitNames} ) { next if $key eq 'max_pbox'; $self->insertLimit( $parent, $parentType, $key, "-1" ); $count++; } } return $count; } my ( $sql, $ptrRow, $value, $name ); $sql = "SELECT limit_name,value FROM Limits WHERE id=$limitId"; if ( $self->{dbh}->execute_rownum($sql) ) { $count = 0; while ( $ptrRow = $self->{dbh}->fetchrow() ) { ( $name, $value ) = @{$ptrRow}; next unless exists $limitNames->{$name}; $self->insertLimit( $parent, $parentType, $name, $value ); $count++; } } $self->{dbh}->finish(); return $count; } # # Gather domain templates information # sub dumpDomainTemplates { my ( $self, $clientId, $clientType ) = @_; return unless PleskVersion::atLeast( 5, 0, 0 ); if (PleskVersion::atLeast( 10, 0, 0 ) and not PleskVersion::isSmb()) { $self->dumpTemplates( $clientId, $clientType, 'domain' ); $self->dumpTemplates( $clientId, $clientType, 'domain_addon' ); } else { my $sql; my $tmpl_id; if ($clientId) { if ( PleskVersion::atLeast( 6, 0, 0 ) ) { $sql = "SELECT tmpl_id FROM clients WHERE id=$clientId"; } else { $sql = "SELECT val FROM cl_param WHERE cl_id=$clientId AND " . "param = 'dom_tmpl_list_id'"; } if ( $self->{dbh}->execute_rownum($sql) ) { if( my $rowPtr = $self->{dbh}->fetchrow() ) { $tmpl_id = @{ $rowPtr }[0]; } } $self->{dbh}->finish(); $self->dumpTemplates9x( $clientId, $clientType, $tmpl_id, 'domain' ) if $tmpl_id; } } } sub dumpTemplates { my ( $self, $parent, $parentType, $templateType ) = @_; return $self->dumpTemplates9x($parent, $parentType, undef, $templateType); } sub dumpTemplates9x { my ( $self, $parent, $parentType, $tmpl_id, $templateType ) = @_; my $proc = undef; if ( $parentType eq 'server' ) { $proc = $self->getSubroutineRef("addTemplateToServer"); } elsif ( $parentType eq 'reseller' ) { if ( 'domain' eq $templateType or 'domain_addon' eq $templateType) { $proc = $self->getSubroutineRef("addResellerDomainTemplate"); } else { Packer::printToError( "Error: dumpTemplates: unexpected template type \"$templateType\" for parent \"$parentType\""); return; } } elsif ( $parentType eq 'client' ) { if ( 'domain' eq $templateType or 'domain_addon' eq $templateType) { $proc = $self->getSubroutineRef("addClientDomainTemplate"); } else { Packer::printToError( "Error: dumpTemplates: unexpected template type \"$templateType\" for parent \"$parentType\""); return; } } else { Packer::printToError( "Error: dumpTemplates: Unexpected type of parent \"$parentType\""); return; } my $sql; my $ownerGuid; my %templateNames; my %templateNotes; my %templateUuids; my %templateExtIds; if (PleskVersion::atLeast( 10, 0, 0 ) and not PleskVersion::isSmb()) { $ownerGuid = PleskStructure::getClientGuidFromId($parent); $sql = "SELECT * FROM Templates WHERE type='$templateType' AND owner_id = $parent"; if ( $self->{dbh}->execute($sql) ) { while ( my $ptrHash = $self->{dbh}->fetchhash() ) { my $id = $ptrHash->{'id'}; $templateNames{ $id } = $ptrHash->{'name'}; $templateUuids{ $id } = $ptrHash->{'uuid'}; $templateExtIds{ $id } = $ptrHash->{'external_id'} if defined $ptrHash->{'external_id'} and $ptrHash->{'external_id'} ne ''; } } } else { $sql = "SELECT t.id, t.name, t.note_id FROM Templates t, Repository r WHERE r.rep_id=$tmpl_id AND r.component_id = t.id"; if ( $self->{dbh}->execute($sql) ) { while ( my $ptrRow = $self->{dbh}->fetchrow() ) { $templateNames{ $ptrRow->[0] } = $ptrRow->[1]; $templateNotes{ $ptrRow->[0] } = $ptrRow->[2]; } } } $self->{dbh}->finish(); my %planItems; my @planItemNames = @{$self->getPlanItemNames()}; while ( my ( $tmpl_id, $tmpl_name ) = each %templateNames ) { my @template; my $logrotation_id; my $ip_pool_id; my $overuse_block; my $overuse_notify; my $overuse_suspend; my $aps_bundle_filter_id = undef; my $sql = "SELECT element, value FROM TmplData WHERE tmpl_id=$tmpl_id"; if ( $self->{dbh}->execute($sql) ) { while ( my $ptrRow = $self->{dbh}->fetchrow() ) { my ( $element, $value ) = @{$ptrRow}; if ( !defined($value) ) { $value = ''; } if ( $element eq 'stat_ttl' and ( $value == 0 or $value eq '' ) ) { $value = -1; } # if ( ($element eq 'disk_space' or $element eq 'max_traffic' or $element eq 'mbox_quota') # and $value == 0 and 'domain_addon' ne $templateType ) { # $value = -1; # } if ( $element eq 'vh_type' and $value ne 'none' and !PleskVersion::atLeast( 6, 0, 0 ) ) { $value = 'physical'; } if ( $element eq 'logrotation_id' ) { $logrotation_id = $value; next; } if ($element eq 'tmpl_pool_id') { $ip_pool_id = $value; next; } if( $element eq 'overuse_block' ){ $overuse_block = $value; next; } if( $element eq 'overuse_notify' ){ $overuse_notify = $value; next; } if ( $element eq 'overuse_suspend' ){ $overuse_suspend = $value; next; } if ( not exists $template_items{$element} ) { if ( PleskVersion::atLeast( 10, 1, 0 ) and not PleskVersion::isSmb() ) { if ( grep $_ eq $element, @planItemNames) { $planItems{ $element } = $value; } if ($element eq 'aps_bundle_filter_id') { $aps_bundle_filter_id = $value; } } next; } if ( 'domain_addon' eq $templateType ) { # skip items which are not allowed for domain_addon template next if exists $template_items_ignore_addon{$element}; } if ( 'domain' eq $templateType ) { # skip items which are not allowed for domain template next if ($element eq 'cp_access' or $element eq 'remote_access_interface'); } if ( $element eq 'quota' and ( $value eq 'false' or $value == 0 ) ) { $value = -1; } if ($element eq 'mbox_quota' and $value != -1 and !PleskVersion::atLeast( 7, 0, 0 ) ) { $value *= 1024; } if ($element eq 'quota' and $value != -1 and !PleskVersion::atLeast( 7, 0, 0 ) ) { $value *= 1024 * 1024; } if ( $value eq '' and exists $emptyableBoolElementInTemplate{$element} ) { $value = 'false'; } my @data = ( $element, $value ); push @template, \@data; } } $self->{dbh}->finish(); my %logRotation; if ( $logrotation_id and ( $templateType eq 'domain' ) ) { %logRotation = $self->makeLogrotationNode($logrotation_id); } my %ipPool; if ( $ip_pool_id and ( $templateType eq 'reseller' or $templateType eq 'client' ) ) { %ipPool = $self->makeTemplateIpPool($ip_pool_id); } unless ( PleskVersion::atLeast( 6, 0, 0 ) ) { my @data = ( 'dns_type', 'master' ); push @template, \@data; } if( $overuse_block and ('domain_addon' ne $templateType )){ my @data = ( 'overuse' ); if( $overuse_block eq 'true' ) { if ( $overuse_suspend ) { if ($overuse_suspend eq 'true') { push @data, 'block'; } else { push @data, 'not_suspend'; } } else { push @data, 'block'; } } elsif( $overuse_notify and $overuse_notify eq 'true' ) { push @data, 'notify'; } else{ push @data, 'normal'; } push @template, \@data; } my @templateAttrs; if ( defined $templateNotes{$tmpl_id} ) { my @noteAttr = ( 'note-id', $templateNotes{$tmpl_id} ); push @templateAttrs, \@noteAttr; } if ( defined $templateUuids{$tmpl_id} ) { my @guidAttr = ( 'guid', $templateUuids{$tmpl_id}); push @templateAttrs, \@guidAttr; } if ( defined $templateExtIds{$tmpl_id} ) { my @extIdAttr = ( 'external-id', $templateExtIds{$tmpl_id}); push @templateAttrs, \@extIdAttr; } if ( defined $ownerGuid ) { my @ownerGuidAttr = ( 'owner-guid', $ownerGuid); push @templateAttrs, \@ownerGuidAttr; } if ( $templateType eq 'domain_addon') { my @isAddonAttr = ( 'is-addon', 'true'); push @templateAttrs, \@isAddonAttr; } my @apsFilterItems; my $filterType; if (defined($aps_bundle_filter_id)) { $sql = "SELECT propertyName, propertyValue FROM smb_apsBundleFilterItems WHERE filterId = '$aps_bundle_filter_id'"; if ($self->{dbh}->execute_rownum($sql)) { while(my $ptrHash = $self->{dbh}->fetchhash()) { push @apsFilterItems, {$ptrHash->{'propertyName'} => $ptrHash->{'propertyValue'}}; } } $self->{dbh}->finish(); $sql = "SELECT type FROM smb_apsBundleFilters WHERE id = '$aps_bundle_filter_id'"; if ( $self->{dbh}->execute_rownum($sql) and my $ptrRow = $self->{dbh}->fetchrow()) { $filterType = $ptrRow->[0]; } $self->{dbh}->finish(); } if ( 'server' eq $parentType ) { $self->{packer}->$proc($templateType, $tmpl_name, \@templateAttrs, \@template, \%planItems, \%logRotation, \%ipPool, \@apsFilterItems, $filterType); } else { $self->{packer}->$proc( $parent, $tmpl_name, \@templateAttrs, \@template, \%planItems, \%logRotation, \%ipPool, \@apsFilterItems , $filterType); } } } sub makeTemplateIpPool { my ( $self, $ip_pool_id ) = @_; my $sql = "SELECT IP_Addresses.`ip_address`, ip_pool.`type`" . " FROM ip_pool". " LEFT JOIN IP_Addresses ON ip_pool.`ip_address_id` = IP_Addresses.`id`" . " WHERE ip_pool.`id` = $ip_pool_id"; my %ipPool = (); if ( $self->{dbh}->execute_rownum($sql) ) { while ( my $ptrRow = $self->{dbh}->fetchrow() ) { $ipPool{ $ptrRow->[0] } = $ptrRow->[1]; } } $self->{dbh}->finish(); return %ipPool; } # # Returns the XML node if domain service is present and undef # otherwise # sub getDomainServiceStatus { my ( $self, $domId, $service ) = @_; my $status = 0; my $sql = "SELECT status FROM DomainServices " . " WHERE dom_id=$domId AND type='$service'"; if ( $self->{dbh}->execute_rownum($sql) and my $ptrRow = $self->{dbh}->fetchrow() ) { $status = $ptrRow->[0]; } else { $status = undef; } $self->{dbh}->finish(); return $status; } # # makeDomainNode # # arguments: # $domainId - domain id # # return: # $root - pointer to XML node # sub makeDomainNode { my ( $self, $domainName, $isroot) = @_; if( $self->domainExcluded( $domainName ) ) { Packer::printToLog("Domain '$domainName' is excluded from dump"); return; } foreach my $dumpedDomain( @{$self->{dumped_domains}} ){ if( $dumpedDomain eq $domainName ){ Packer::printToLog("Domain '$domainName' already dumped"); return; } } push @{$self->{dumped_domains}}, $domainName; Packer::printToLog("Domain '$domainName' is started"); $self->{dump_status}->startDomain($domainName); my ( $sql, %domain, %domParams, $ptrRow, $ptrHash, $id ); # # get domain's info # my $domainNameColumn = 'name'; if ( PleskVersion::atLeast( 7, 1, 0 ) ) { $domainNameColumn = 'displayName'; } Packer::printToLog("Getting domain info"); $sql = "SELECT * FROM domains WHERE $domainNameColumn = '$domainName'"; unless ( $self->{dbh}->execute_rownum($sql) ) { $self->{dbh}->finish(); return; } unless ( $ptrHash = $self->{dbh}->fetchhash() ) { $self->{dbh}->finish(); return; } %domain = %{$ptrHash}; $self->{dbh}->finish(); my $domainId = $domain{'id'}; my $clientId = $domain{'cl_id'}; if ( exists $domain{'vendor_id'} ){ my $vendorGuid = PleskStructure::getClientGuidFromId( $domain{'vendor_id'} ); $domain{'vendor-guid'} = $vendorGuid; } my $clientPermsId; if ( PleskVersion::atLeast( 6, 0, 0 ) ) { $sql = "SELECT perm_id FROM clients WHERE id = $clientId"; } else { $sql = "SELECT val FROM cl_param WHERE cl_id = $clientId AND param = 'perm_id'"; } if ( $self->{dbh}->execute_rownum($sql) and my $ptrRow = $self->{dbh}->fetchrow() ) { $clientPermsId = $ptrRow->[0]; } $self->{dbh}->finish(); $sql = "SELECT param,val FROM dom_param WHERE dom_id=$domainId"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( $ptrRow = $self->{dbh}->fetchrow() ) { $domParams{ $ptrRow->[0] } = $ptrRow->[1]; } } $self->{dbh}->finish(); # # end get domain's info # my $domainAsciiName; if ( PleskVersion::atLeast( 7, 1, 0 ) ) { $domainName = $domain{'displayName'}; $domainAsciiName = $domain{'name'}; } else { $domainName = $domain{'name'}; } my $domainOwner = PleskStructure::getClientNameFromId( $domain{'cl_id'} ); my $parentType = PleskStructure::getClientType( $domainOwner ); if( $isroot ){ $self->{packer}->addRootDomain( $domainId, $domainName, $domainAsciiName, \%domain, PleskStructure::getClientGuid($domainOwner) ); } else{ if( $parentType eq 'admin' ){ $self->{packer}->addAdminDomain( $domainId, $domainName, $domainAsciiName, \%domain ); } elsif( $parentType eq 'reseller' ){ $self->{packer}->addResellerDomain( $domain{'cl_id'}, $domainId, $domainName, $domainAsciiName, \%domain ); } elsif( $parentType eq 'client' ){ $self->{packer}->addClientDomain( $domain{'cl_id'}, $domainId, $domainName, $domainAsciiName, \%domain ); } else{ die "Cannot dump domain '$domainName'. Domain owner '$domainOwner' type '$parentType' is not supported!"; } } $self->suspendDomain( $domainName ); my $domainAsciiName = $domain{'name'}; my $domainType = $domain{'htype'}; $self->addWwwStatus( $domainId, $domainAsciiName ); # Domain's IP address Packer::printToLog("Getting domain IP"); my $ip = PleskStructure::getDomainIp($domainName); if ($ip) { $self->{packer}->setDomainIP( $domainId, $ip, PleskStructure::getClientIpType( $domainOwner, $ip ) ); } # # Status # Packer::printToLog("Dumping domain status"); my $status = 0; my $siteStatus = undef; if ( PleskVersion::atLeast( 5, 1, 0 ) ) { $status = $domain{'status'}; if ($domain{'status'} != $Status::ENABLED) { $siteStatus = $Status::WITH_PARENT; } if ( PleskVersion::atLeast( 10, 0, 0 ) and not PleskVersion::isSmb() ) { $status += 0; $status = $domain{'webspace_status'}; $siteStatus = $domain{'status'}; } } else { $status |= $Status::ADMIN if $domain{'admin_status'} eq 'false'; $status |= $Status::CLIENT if $domain{'status'} eq 'false'; } $self->{packer}->setWebspaceStatus( $domainId, $status, $siteStatus ); # # No further info required if shallow dump specified # if ( $self->{shallow_dump} && !$self->{only_mail_dump} ) { # Need to dump information about all databases for DbServers mapping Packer::printToLog("Dumping domain databases"); $sql = "SELECT id FROM data_bases WHERE dom_id=$domainId"; if ( $self->{dbh}->execute_rownum($sql) ) { my (@databases); while ( $ptrRow = $self->{dbh}->fetchrow() ) { push @databases, $ptrRow->[0]; } foreach my $dbid (@databases) { $self->makeDatabaseNode( $dbid, $domainId, 'domain', undef, undef ); } } # Domain's DNS settings $self->makeDomainDnsZone( \%domain ); if ((!defined $ip) && ( $domainType ne 'vrt_hst' ) ) { my $preferredIp = $self->{packer}->getDomainARecordIp($domainId); my $type; $ip = PleskStructure::getIp4DomainWoHosting($domainId, $preferredIp, \$type); if ( $ip ) { $self->{packer}->setDomainIP( $domainId, $ip, $type ); } } $self->{packer}->removeDomainDnsZone($domainId); $self->{dbh}->finish(); $self->unSuspendDomain(); $self->{packer}->finishDomain($domainId); $self->{dump_status}->endDomain($domainName); return; } # Check whether this domain is default on IP if ( PleskVersion::atLeast( 6, 0, 0 ) ) { $sql = "SELECT COUNT(*) FROM IP_Addresses WHERE default_domain_id=$domainId"; if ( $self->{dbh}->execute_rownum($sql) ) { if ( @{ $self->{dbh}->fetchrow() }[0] ne "0" ) { $self->{packer}->setDomainDefault($domainId); } } $self->{dbh}->finish(); } else { if ( PleskStructure::isExclusiveIp($ip) ) { $self->{packer}->setDomainDefault($domainId); } } # Domain's DNS settings $self->makeDomainDnsZone( \%domain ); if ( !$self->{only_mail_dump} ) { # Domain's aliases $self->dumpDomainAliases($domainId); } if ((!defined $ip) && ( $domainType ne 'vrt_hst' ) ) { my $preferredIp = $self->{packer}->getDomainARecordIp($domainId); my $type; $ip = PleskStructure::getIp4DomainWoHosting($domainId, $preferredIp, \$type); if ( $ip ) { $self->{packer}->setDomainIP( $domainId, $ip, $type ); } } Packer::printToLog("Getting domain limits"); # # limits # if ( !$self->{only_mail_dump} ) { if ( PleskVersion::atLeast( 6, 0, 0 ) ) { $self->addDomainLimits( $domainId, $domain{'limits_id'} ); $self->addOverusePolicy( 'domain', $domainId, \%domParams ); } elsif ( PleskVersion::atLeast( 5, 0, 0 ) ) { $self->addDomainLimits( $domainId, $domParams{'lim_id'} ); } else { $self->addDomainLimits25( $domainId, $domParams{'lim_id'} ); } $self->{packer}->fixDefaultLimits('domain',$domainId); } # # end limits # # # permissions # if ( !$self->{only_mail_dump} ) { if ( PleskVersion::atLeast( 10, 0, 0) and not PleskVersion::isSmb() ) { $self->dumpDomainPersonalPermissions( $domainId, $domain{'permissions_id'} ); } else { $self->dumpDomainPersonalPermissions( $domainId, $clientPermsId ); } } # # end permissions # if ( !$self->{only_hosting_dump} ) { Packer::printToLog("Dumping domain mailsystem"); my $mailServiceStatus; if (PleskVersion::atLeast(6, 0, 0)) { $mailServiceStatus = $self->getDomainServiceStatus($domainId, 'mail'); } else { $mailServiceStatus = Status::make($Status::ENABLED); } if ( defined($mailServiceStatus) ) { $self->{packer}->setDomainMailService( $domainId, $mailServiceStatus ); if (PleskVersion::atLeast(6, 0, 0)) { $sql = "SELECT m.id, a.password, a.type FROM mail m". " LEFT JOIN accounts a ON m.account_id=a.id ". " WHERE m.dom_id=$domainId ORDER BY m.mail_name"; } else { $sql = "SELECT id, password, 'plain' FROM mail ". " WHERE dom_id=$domainId ORDER BY mail_name"; } if ( $self->{dbh}->execute_rownum($sql) ) { my (@mails); while ( $ptrRow = $self->{dbh}->fetchrow() ) { push @mails, [ @{$ptrRow} ]; } $self->{packer}->setDomainMailNamesContent( $domainId, $domainName, getPleskMailnamesDir() . "/$domainAsciiName/" ) if $self->{dump_full_mail}; foreach $ptrRow (@mails) { $ptrRow->[2] = $self->{packer}->normalizePasswordType( $ptrRow->[2] ); if ($isroot and not PleskVersion::atLeast(10, 0, 0)) { $parentType = 'root'; } $self->makeMailUserNode( $domainId, @{$ptrRow}, $domainName, $domainAsciiName, $parentType, $domain{'cl_id'} ); } } $self->{dbh}->finish(); $self->getCatchAllAddress($domainId); $self->getDomainKeysDomainSupport( $domainId, $domainName, $domain{'dns_zone_id'} ); my $oldWebMailFlag = undef; if (!PleskVersion::atLeast(9, 0, 0)) { $oldWebMailFlag = $self->getOldWebMailStatus(\%domain); } $self->{packer}->setDomainWebMail( $domainId, ( exists $domParams{'webmail'} ? $domParams{'webmail'} : defined($oldWebMailFlag) ? 'horde' : 'none' ) ); $self->{packer}->setDomainGLSupport( $domainId, (exists $domParams{'gl_filter'} ) ? $domParams{'gl_filter'} : 'on' ); } } else { Packer::printToLog("Skip domain mailsystem dump due to settings"); } my @SiteApplications; if ( !$self->{only_mail_dump} ) { #----------------------------------------------------------------- # Information about domain's site applications # should be extracted prior to database/hosting/custom-buttons # dump, as site applications' linked resources should be dumped # separately. #----------------------------------------------------------------- @SiteApplications = $self->getDomainSiteapps($domainId, $self->{dbh}); #----------------------------------------------------------------- # Domain's databases #----------------------------------------------------------------- Packer::printToLog("Dumping domain databases"); # Site applications' databases should not be dumped here my $exclude_list = ''; { my @excluded_dbs; foreach my $sapp (@SiteApplications) { foreach my $row ( $sapp->getDatabases() ) { push @excluded_dbs, $row->{'id'}; } } if (@excluded_dbs) { $exclude_list = " AND id NOT IN(" . Packer::getSqlList(@excluded_dbs) . ")"; } } # Databases without those used in site apps $sql = "SELECT id FROM data_bases WHERE dom_id=$domainId" . $exclude_list; if ( $self->{dbh}->execute_rownum($sql) ) { my (@databases); while ( $ptrRow = $self->{dbh}->fetchrow() ) { push @databases, $ptrRow->[0]; } foreach my $dbid (@databases) { $self->makeDatabaseNode( $dbid, $domainId, 'domain', undef, undef ); } } $self->{dbh}->finish(); } else { Packer::printToLog("Skip dumping domain databases due to settings"); } # # maillist # if ( !$self->{only_hosting_dump} ) { Packer::printToLog("Dumping domain maillists"); if ( PleskVersion::atLeast( 6, 0, 0 ) ) { my $maillistsStatus = $self->getDomainServiceStatus( $domainId, 'maillists' ); if (defined $maillistsStatus) { $self->{packer}->setDomainMailLists( $domainId, $maillistsStatus ); my $archiveDir = AgentConfig::get("MAILMAN_VAR_D") . "/archives/private"; my @archiveDirs; $sql = "SELECT id,name,status FROM MailLists WHERE dom_id=$domainId"; if ( $self->{dbh}->execute_rownum($sql) ) { my (@mlists); while ( $ptrRow = $self->{dbh}->fetchrow() ) { push @mlists, [ @{$ptrRow} ]; my $datafile = $ptrRow->[1] . ".mbox/" . $ptrRow->[1] . ".mbox"; push @archiveDirs, $datafile if -f "$archiveDir/$datafile"; } $self->{packer}->setDomainMailListContent( $domainId, $domainAsciiName, $archiveDir, { 'include' => \@archiveDirs, 'follow_symlinks' => 1 } ) if $self->{dump_full_mail}; foreach $ptrRow (@mlists) { $self->makeMailListNode( $domainId, @{$ptrRow} ); } } $self->{dbh}->finish(); } } } else { Packer::printToLog("Skip dumping domain maillists due to settings"); } # # end maillist # if ( !$self->{only_mail_dump} ) { Packer::printToLog("Dumping domain statistics"); $self->addDomainTraffic($domainId); if ( PleskVersion::atLeast( 6, 0, 0 ) ) { my $cert_id = $domain{'cert_rep_id'}; $cert_id = '' unless ( defined($cert_id) ); $sql = "SELECT c.id FROM certificates c, Repository r " . "WHERE c.id=r.component_id AND r.rep_id='$cert_id' ORDER BY c.id"; } else { $sql = "SELECT id FROM certificates WHERE dom_id=$domainId"; } my @ids; if ( $self->{dbh}->execute_rownum($sql) ) { while ( $ptrRow = $self->{dbh}->fetchrow() ) { push @ids, $ptrRow->[0]; } } $self->{dbh}->finish(); my $defaultCert = -1; $sql = "SELECT c.id FROM domains d, hosting h, IP_Addresses ip, certificates c " . "WHERE c.id=ip.ssl_certificate_id AND ip.id=h.ip_address_id AND h.dom_id=d.id AND d.id=$domainId"; if ( $self->{dbh}->execute_rownum($sql) and $ptrRow = $self->{dbh}->fetchrow() ) { $defaultCert = $ptrRow->[0]; } $self->{dbh}->finish(); foreach $id (@ids) { $self->makeCertificateNode( $id, $domainId, 'domain', $id == $defaultCert ); } my $tomcatServiceStatus; if ( PleskVersion::atLeast( 6, 0, 0 ) ) { $tomcatServiceStatus = $self->getDomainServiceStatus( $domainId, 'tomcat' ); } if (defined $tomcatServiceStatus) { $self->{packer}->setDomainTomcat( $domainId, $tomcatServiceStatus ); $sql = "SELECT wa.name,wa.status FROM WebApps wa LEFT JOIN DomainServices ds ON wa.domain_service_id=ds.id WHERE ds.dom_id = $domainId"; my ( %webapps, $webapp ); if ( $self->{dbh}->execute_rownum($sql) ) { while ( $ptrRow = $self->{dbh}->fetchrow() ) { $webapps{ $ptrRow->[0] } = $ptrRow->[1]; } } $self->{dbh}->finish(); foreach $webapp ( keys %webapps ) { $self->makeWebAppNode( $domainId, $webapp, $webapps{$webapp}, $domainAsciiName ); } } if( not PleskVersion::atLeast(10, 0, 0)) { if ( $isroot ) { $self->makeDomAdminUserRole('root', $domain{'cl_id'}, $domainId, \%domParams); } else { $self->makeDomAdminUserRole(PleskStructure::getClientType( $domainOwner ), $domain{'cl_id'}, $domainId, \%domParams); } } } if ( $domainType eq "vrt_hst" ) { $self->makePhostingNode( \%domain, \%domParams, \@SiteApplications ); } elsif ( $domainType eq "std_fwd" ) { $self->makeShostingNode( \%domain ); } elsif ( $domainType eq "frm_fwd" ) { $self->makeFhostingNode( \%domain ); } if ( !$self->{only_mail_dump} ) { $self->getCustomButtonsByOwner( 'domain-admin', $domainId ); if ( PleskVersion::atLeast( 10, 0, 0 ) and not PleskVersion::isSmb() ) { $self->getSubscription('domain', $domainId); if ( PleskVersion::atLeast( 10, 1, 0 ) ) { $self->getSubscriptionProperties('domain', $domainId); $self->dumpApsBundle($domainId, 'domain'); } $self->{packer}->dumpUnityMobileIntegration($domainId, \%domParams); } } $self->unSuspendDomain(); $self->{dump_status}->endDomain($domainName); $self->{packer}->finishDomain($domainId); } # # makeSiteNode # sub makeSiteNode { my ( $self, $domainAsciiName, $domainName) = @_; my ( $sql, %domain, %domParams, $ptrRow, $ptrHash, $id ); # # get domain's info # Packer::printToLog("Getting site info"); $sql = "SELECT * FROM domains WHERE name = '$domainAsciiName'"; unless ( $self->{dbh}->execute_rownum($sql) ) { $self->{dbh}->finish(); return; } unless ( $ptrHash = $self->{dbh}->fetchhash() ) { $self->{dbh}->finish(); return; } %domain = %{$ptrHash}; $self->{dbh}->finish(); my $domainId = $domain{'id'}; my $webspaceId = $domain{'webspace_id'}; $sql = "SELECT param,val FROM dom_param WHERE dom_id=$domainId"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( $ptrRow = $self->{dbh}->fetchrow() ) { $domParams{ $ptrRow->[0] } = $ptrRow->[1]; } } $self->{dbh}->finish(); # # end get domain's info # my $domainType = $domain{'htype'}; my $domainOwner = PleskStructure::getClientNameFromId( $domain{'cl_id'} ); my $parentType = PleskStructure::getClientType( $domainOwner ); $self->{packer}->addDomainSite( $webspaceId, $domainId, $domainAsciiName, $domainName, \%domain ); $self->suspendDomain( $domainName ); $self->addWwwStatus( $domainId, $domainAsciiName ); # # Status # Packer::printToLog("Dumping site status"); my $status = $domain{'status'}; $self->{packer}->setDomainStatus( $domainId, $status ); # Domain's DNS settings $self->makeDomainDnsZone( \%domain ); if ( !$self->{only_mail_dump} ) { # Domain's aliases $self->dumpDomainAliases($domainId); } # # No further info required if shallow dump specified # if ( $self->{shallow_dump} && !$self->{only_mail_dump} ) { # Need to dump information about all databases for DbServers mapping Packer::printToLog("Dumping domain databases"); $sql = "SELECT id FROM data_bases WHERE dom_id=$domainId"; if ( $self->{dbh}->execute_rownum($sql) ) { my (@databases); while ( $ptrRow = $self->{dbh}->fetchrow() ) { push @databases, $ptrRow->[0]; } foreach my $dbid (@databases) { $self->makeDatabaseNode( $dbid, $domainId, 'domain', undef, undef ); } } $self->{dbh}->finish(); $self->unSuspendDomain(); $self->{packer}->finishDomain($domainId); return; } if ( !$self->{only_hosting_dump} ) { Packer::printToLog("Dumping site mailsystem"); my $mailServiceStatus; $mailServiceStatus = $self->getDomainServiceStatus($domainId, 'mail'); if ( defined($mailServiceStatus) ) { $self->{packer}->setDomainMailService( $domainId, $mailServiceStatus ); $sql = "SELECT m.id, a.password, a.type FROM mail m". " LEFT JOIN accounts a ON m.account_id=a.id ". " WHERE m.dom_id=$domainId ORDER BY m.mail_name"; if ( $self->{dbh}->execute_rownum($sql) ) { my (@mails); while ( $ptrRow = $self->{dbh}->fetchrow() ) { push @mails, [ @{$ptrRow} ]; } $self->{packer}->setDomainMailNamesContent( $domainId, $domainName, getPleskMailnamesDir() . "/$domainAsciiName/" ) if $self->{dump_full_mail}; foreach $ptrRow (@mails) { $ptrRow->[2] = $self->{packer}->normalizePasswordType( $ptrRow->[2] ); $self->makeMailUserNode( $domainId, @{$ptrRow}, $domainName, $domainAsciiName ); } } $self->{dbh}->finish(); $self->getCatchAllAddress($domainId); $self->getDomainKeysDomainSupport( $domainId, $domainName, $domain{'dns_zone_id'} ); my $oldWebMailFlag = $self->getOldWebMailStatus(\%domain); $self->{packer}->setDomainWebMail( $domainId, ( exists $domParams{'webmail'} ? $domParams{'webmail'} : defined($oldWebMailFlag) ? 'horde' : 'none' ) ); $self->{packer}->setDomainGLSupport( $domainId, (exists $domParams{'gl_filter'} ) ? $domParams{'gl_filter'} : 'on' ); } } else { Packer::printToLog("Skip site mailsystem dump due to settings"); } my @SiteApplications; if ( !$self->{only_mail_dump} ) { #----------------------------------------------------------------- # Information about domain's site applications # should be extracted prior to database/hosting/custom-buttons # dump, as site applications' linked resources should be dumped # separately. #----------------------------------------------------------------- @SiteApplications = $self->getDomainSiteapps($domainId, $self->{dbh}); #----------------------------------------------------------------- # Domain's databases #----------------------------------------------------------------- Packer::printToLog("Dumping site databases"); # Site applications' databases should not be dumped here my $exclude_list = ''; { my @excluded_dbs; foreach my $sapp (@SiteApplications) { foreach my $row ( $sapp->getDatabases() ) { push @excluded_dbs, $row->{'id'}; } } if (@excluded_dbs) { $exclude_list = " AND id NOT IN(" . Packer::getSqlList(@excluded_dbs) . ")"; } } # Databases without those used in site apps $sql = "SELECT id FROM data_bases WHERE dom_id=$domainId" . $exclude_list; if ( $self->{dbh}->execute_rownum($sql) ) { my (@databases); while ( $ptrRow = $self->{dbh}->fetchrow() ) { push @databases, $ptrRow->[0]; } $self->{dbh}->finish(); foreach my $dbid (@databases) { $self->makeDatabaseNode( $dbid, $domainId, 'domain', undef, undef ); } } else{ $self->{dbh}->finish(); } } else { Packer::printToLog("Skip dumping domain databases due to settings"); } # # maillist # if ( !$self->{only_hosting_dump} ) { Packer::printToLog("Dumping site maillists"); my $maillistsStatus = $self->getDomainServiceStatus( $domainId, 'maillists' ); if (defined $maillistsStatus) { $self->{packer}->setDomainMailLists( $domainId, $maillistsStatus ); my $archiveDir = AgentConfig::get("MAILMAN_VAR_D") . "/archives/private"; my @archiveDirs; $sql = "SELECT id,name,status FROM MailLists WHERE dom_id=$domainId"; if ( $self->{dbh}->execute_rownum($sql) ) { my (@mlists); while ( $ptrRow = $self->{dbh}->fetchrow() ) { push @mlists, [ @{$ptrRow} ]; my $datafile = $ptrRow->[1] . ".mbox/" . $ptrRow->[1] . ".mbox"; push @archiveDirs, $datafile if -f "$archiveDir/$datafile"; } $self->{packer}->setDomainMailListContent( $domainId, $domainAsciiName, $archiveDir, { 'include' => \@archiveDirs, 'follow_symlinks' => 1 } ) if $self->{dump_full_mail}; foreach $ptrRow (@mlists) { $self->makeMailListNode( $domainId, @{$ptrRow} ); } } $self->{dbh}->finish(); } } else { Packer::printToLog("Skip site domain maillists due to settings"); } # # end maillist # if ( !$self->{only_mail_dump} ) { Packer::printToLog("Dumping site statistics"); $self->addDomainTraffic($domainId); my $cert_id = $domain{'cert_rep_id'}; $cert_id = '' unless ( defined($cert_id) ); $sql = "SELECT c.id FROM certificates c, Repository r " . "WHERE c.id=r.component_id AND r.rep_id='$cert_id' ORDER BY c.id"; my @ids; if ( $self->{dbh}->execute_rownum($sql) ) { while ( $ptrRow = $self->{dbh}->fetchrow() ) { push @ids, $ptrRow->[0]; } } $self->{dbh}->finish(); foreach $id (@ids) { $self->makeCertificateNode( $id, $domainId, 'domain' ); } my $tomcatServiceStatus = $self->getDomainServiceStatus( $domainId, 'tomcat' ); if (defined $tomcatServiceStatus) { $self->{packer}->setDomainTomcat( $domainId, $tomcatServiceStatus ); $sql = "SELECT wa.name,wa.status FROM WebApps wa LEFT JOIN DomainServices ds ON wa.domain_service_id=ds.id WHERE ds.dom_id = $domainId"; my ( %webapps, $webapp ); if ( $self->{dbh}->execute_rownum($sql) ) { while ( $ptrRow = $self->{dbh}->fetchrow() ) { $webapps{ $ptrRow->[0] } = $ptrRow->[1]; } } $self->{dbh}->finish(); foreach $webapp ( keys %webapps ) { $self->makeWebAppNode( $domainId, $webapp, $webapps{$webapp}, $domainAsciiName ); } } if ( $domainType eq "vrt_hst" ) { $self->makePhostingNode( \%domain, \%domParams, \@SiteApplications, 1 ); } elsif ( $domainType eq "std_fwd" ) { $self->makeShostingNode( \%domain ); } elsif ( $domainType eq "frm_fwd" ) { $self->makeFhostingNode( \%domain ); } $self->getCustomButtonsByOwner( 'domain-admin', $domainId ); $self->getSubscription('domain', $domainId); $self->{packer}->dumpUnityMobileIntegration($domainId, \%domParams); } $self->unSuspendDomain(); $self->{packer}->finishDomain($domainId); } #----------------------------------------------------------------- # Returns or xml elements #----------------------------------------------------------------- sub makeDomainDnsZone( $ ) { my ( $self, $domainHashPtr ) = @_; Packer::printToLog("Dumping domain DNS"); if ( PleskVersion::atLeast( 8, 0, 0 ) ) { return $self->makeDnsZone( $domainHashPtr->{'dns_zone_id'}, $domainHashPtr->{'id'}, 'domain' ); } else { return $self->makeDnsZoneOld( $domainHashPtr->{'id'} ); } } #----------------------------------------------------------------- # Returns xml node or false if given record should not be dumped #----------------------------------------------------------------- sub makeDnsRecord( $ ) { my ( $self, $ptrHash ) = @_; return if $ptrHash->{'type'} =~ /none/; return if $ptrHash->{'displayHost'} =~ /.*_domainkey.*/; if ( $ptrHash->{'type'} eq 'TXT' ) { $ptrHash->{'val'} =~ s/"(.*)"/$1/; } # Fix broken CNAME mail records (bug #110731) if ( $ptrHash->{'type'} eq 'CNAME' and $ptrHash->{'host'} eq "mail." . $ptrHash->{'val'} ) { $ptrHash->{'type'} = 'A'; $ptrHash->{'val'} =~ s/\.$//; if (defined($ptrHash->{'displayVal'})) { delete($ptrHash->{'displayVal'}); } $ptrHash->{'val'} = PleskStructure::getDomainIp( $ptrHash->{'val'} ); } return %{$ptrHash}; } sub geteDnsZone { my ( $self, $dnsZoneId, $paramsPtr, $recordsPtr ) = @_; my $sql = "SELECT * FROM dns_zone WHERE id=$dnsZoneId"; if ( !$self->{dbh}->execute_rownum($sql) ) { $self->{dbh}->finish(); my $msg = "Broken referencial integrity: DNS zone id $dnsZoneId is not found in dns_zone"; print STDERR "$msg\n"; Packer::printToError( $msg ); return; } if ( my $hashPtr = $self->{dbh}->fetchhash($sql) ) { %{$paramsPtr} = %{ $hashPtr }; } $self->{dbh}->finish(); # dns records $sql = "SELECT * FROM dns_recs WHERE dns_zone_id=$dnsZoneId"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( my $ptrHash = $self->{dbh}->fetchhash() ) { my %dnsrec = $self->makeDnsRecord($ptrHash); if (%dnsrec) { push @{$recordsPtr}, \%dnsrec; } } } $self->{dbh}->finish(); } sub makeDnsZone{ my ( $self, $dnsZoneId, $parent, $parentType ) = @_; my $proc; if ( 'domain' eq $parentType ) { $proc = $self->getSubroutineRef("setDomainDnsZone"); } else { Packer::printToError('Error: makeDnsZone: Unexpected type of parent \"$parentType\"'); return; } my %params; my @records; $self->geteDnsZone( $dnsZoneId, \%params, \@records ); $self->{packer}->$proc( $parent, \%params, \@records ); } sub makeDnsZoneOld( $ ) { my ( $self, $domainId ) = @_; my $sql = "SELECT dns_zone"; if ( PleskVersion::atLeast( 5, 0, 0 ) ) { $sql .= ",dns_type"; } $sql .= " FROM domains WHERE id='$domainId'"; my ( $enabled, $type ); if ( $self->{dbh}->execute_rownum($sql) and my $ptrRow = $self->{dbh}->fetchrow() ) { $enabled = $ptrRow->[0] eq 'false' ? 'false' : 'true'; $type = ( !$ptrRow->[1] or ( $ptrRow->[1] eq 'master' ) ) ? 'master' : 'slave'; } $self->{dbh}->finish(); my @records; $sql = "SELECT * FROM dns_recs WHERE dom_id=$domainId"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( my $ptrHash = $self->{dbh}->fetchhash() ) { push @records, $ptrHash; } } $self->{dbh}->finish(); # Add old master record my $masterIp; $sql = "SELECT * FROM dns_masters WHERE dom_id = '$domainId'"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( my $ptrHash = $self->{dbh}->fetchhash() ) { $masterIp = $ptrHash->{'ip_address'}; } } $self->{dbh}->finish(); $self->{packer}->setDomainDnsOld( $domainId, $enabled, $type, $masterIp, \@records ); } #----------------------------------------------------------------- # Dumps domain aliases for given domain ID #----------------------------------------------------------------- sub dumpDomainAliases( $ $ ) { my ( $self, $domainId ) = @_; # Domain aliases are introduced since Plesk 8.0.0 if ( !PleskVersion::atLeast( 8, 0, 0 ) ) { return; } Packer::printToLog( 'Dumping domain aliases... ', 1 ); my @aliases; my $sql = "SELECT * FROM domainaliases WHERE dom_id='$domainId'"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( my $ptrHash = $self->{dbh}->fetchhash() ) { push @aliases, $ptrHash; } } $self->{dbh}->finish(); foreach my $alias (@aliases) { my %params; my @records; if ( $alias->{'dns_zone_id'} != 0 ) { $self->geteDnsZone( $alias->{'dns_zone_id'}, \%params, \@records ); } $self->{packer}->addDomainAlias( $domainId, $alias, \%params, \@records ); } Packer::printToLog('OK'); } sub getDomainSiteapps( $ $ ) { my ($self, $dom_id, $dbh) = @_; # Site applications migration is supported since Plesk 7.0.0 if ( !PleskVersion::atLeast( 7, 0, 0 ) ) { return; } if ( PleskVersion::atLeast( 10, 0, 0 ) and not PleskVersion::isSmb() ) { return SiteApp10::getDomainSiteapps($dom_id); } else { return SiteApp::getDomainSiteapps($dom_id, $dbh); } } sub addWwwStatus { my ( $self, $domainId, $domainName ) = @_; my $sql; if ( PleskVersion::atLeast( 8, 0, 0 ) ) { $sql = "SELECT r.* FROM dns_recs r, domains d WHERE d.id=$domainId " . "AND d.dns_zone_id=r.dns_zone_id AND ( r.type = 'CNAME' or r.type = 'A' ) AND r.host = 'www.$domainName.'"; } else { $sql = "SELECT * FROM dns_recs WHERE dom_id = $domainId AND ( type = 'CNAME' OR type = 'A' ) " . "AND host = 'www.$domainName.'"; } if ( $self->{dbh}->execute_rownum($sql) ) { $self->{packer}->setDomainWwwStatus( $domainId, 'true' ); } else { $self->{packer}->setDomainWwwStatus( $domainId, 'false' ); } $self->{dbh}->finish(); } my %domAdminPermsToRolePerms = ( 'manage_log' => 'logRotationManagement', 'manage_anonftp' => 'anonymousFtpManagement', 'manage_crontab' => 'scheduledTasksManagement', 'manage_spamfilter' => 'spamfilterManagement', 'allow_local_backups'=> 'backupRestoreManagement', 'allow_ftp_backups' => 'backupRestoreManagement', 'manage_virusfilter' => 'antivirusManagement', 'manage_dns' => 'dnsManagement', 'manage_webapps' => 'javaApplicationsManagement', 'manage_maillists' => 'mailListsManagement', 'site_builder' => 'sitebuilderManagement' ); my %domAdminCardToUser = ( 'companyName' => 'companyName', 'personalName'=> 'contactName', 'phone' => 'phone', 'fax' => 'fax', 'email' => 'email', 'address' => 'address', 'city' => 'city', 'state' => 'state', 'zip' => 'zip', 'country' => 'country' ); sub makeDomAdminUserRole { my ( $self, $parentType, $clientId, $domainId, $domParams ) = @_; my ( $sql, $item, $ptrHash, $xmlName, $fieldName ); $sql = "SELECT * FROM dom_level_usrs WHERE dom_id=$domainId"; unless ( $self->{dbh}->execute_rownum($sql) ) { $self->{dbh}->finish(); return; } my %domainUser; if ( $ptrHash = $self->{dbh}->fetchhash() ) { %domainUser = %{ $ptrHash }; } $self->{dbh}->finish(); my $state; if ( $domainUser{'state'} ) { $state = $domainUser{'state'}; } my $passwd; my $passwdType; if ( PleskVersion::atLeast( 7, 1, 5 ) ) { if ( defined $domainUser{'account_id'} and $domainUser{'account_id'} != 0 ) { ( $passwd, $passwdType ) = $self->makeAccountPasswordNode( $domainUser{'account_id'} ); } } else { $passwd = $domainUser{'passwd'}; $passwdType = 'plain'; } my %cardHash; if ( PleskVersion::atLeast( 5, 0, 0 ) && defined( $domainUser{'card_id'} ) ) { $sql = "SELECT * from Cards WHERE id=$domainUser{'card_id'}"; if ( $self->{dbh}->execute_rownum($sql) ) { if ( $ptrHash = $self->{dbh}->fetchhash() ) { %cardHash = %{$ptrHash}; } else { my $msg = "Broken referencial integrity: Card info is not found for domain user"; print STDERR "$msg\n"; Packer::printToError( $msg ); } } $self->{dbh}->finish(); } my $domainName = PleskStructure::getDomainNameFromId($domainId); my $roleName = "Domain Administrator (" . $domainName . ")"; my %userHash; foreach my $item ( keys %cardHash ) { if ( exists $domAdminCardToUser{$item} ) { $userHash{ $domAdminCardToUser{$item} } = $cardHash{ $item }; } } if ( (!defined ($userHash{'contactName'}) ) || ($userHash{'contactName'} eq '') ) { $userHash{'contactName'} = "Domain Administrator (" . $domainName . ")"; } $userHash{'password'} = $passwd; $userHash{'SmbRoleName'} = $roleName; $userHash{'isDomainAdmin'} = '1'; $userHash{'isBuiltIn'} = 0; $userHash{'uuid'} = ''; $userHash{'isLocked'} = 1; $userHash{'isBase64'} = '0'; my $permsHash = $self->getPermsHash( $domainUser{'perm_id'} ); my %rolePermsHash = (); foreach my $perm ( keys %{$permsHash} ) { if ( $permsHash->{$perm} eq 'true' && exists $domAdminPermsToRolePerms{$perm} ) { $rolePermsHash{ $domAdminPermsToRolePerms{$perm} } = 1; } } $rolePermsHash{'browseStats'} = 1; if( $parentType eq 'root' ){ $self->{packer}->addRootUser( $domainName, \%userHash); $self->{packer}->addRootRole( $roleName, 0, \%rolePermsHash); } elsif( $parentType eq 'admin' ){ $self->{packer}->addAdminUser( $domainName, \%userHash); $self->{packer}->addAdminRole( $roleName, 0, \%rolePermsHash); } elsif( $parentType eq 'reseller' || $parentType eq 'client'){ $self->{packer}->addClientUser( $clientId, $domainName, \%userHash); $self->{packer}->addClientRole( $clientId, $roleName, 0, \%rolePermsHash); } } sub makeMailAccessUserRole { my ( $self, $mailname, $domainName, $password, $passwordType, $parentType, $clientId, $antispam, $antivirus ) = @_; return if PleskVersion::atLeast(10, 0, 0); my $perms; $perms = (defined $antispam)? ( "antispam" . ((defined $antivirus)? "; antivirus" : '' ) ): ( (defined $antivirus)? "antivirus" : undef ); my $roleName = "Mail User" . ((defined $perms)? " ($perms)" : ''); my %userHash; $userHash{'SmbRoleName'} = $roleName; $userHash{'isDomainAdmin'} = '0'; $userHash{'isBuiltIn'} = 0; $userHash{'uuid'} = ''; $userHash{'isLocked'} = 0; $userHash{'contactName'} = $mailname; $userHash{'email'} = $mailname.'@'.$domainName; $userHash{'password'} = $password; $userHash{'passwordType'} = $passwordType; $userHash{'isBase64'} = '0'; my %rolePermsHash = (); $rolePermsHash{ 'spamfilterManagement' } = 1 if defined $antispam; $rolePermsHash{ 'antivirusManagement' } = 1 if defined $antivirus; if( $parentType eq 'admin' ) { $self->{packer}->addAdminUser( $mailname.'@'.$domainName, \%userHash); $self->{packer}->addAdminRole( $roleName, 0, \%rolePermsHash); } elsif( $parentType eq 'reseller' || $parentType eq 'client') { $self->{packer}->addClientUser( $clientId, $mailname.'@'.$domainName, \%userHash); $self->{packer}->addClientRole( $clientId, $roleName, 0, \%rolePermsHash); } elsif( $parentType eq 'root' ) { $self->{packer}->addRootUser( $mailname.'@'.$domainName, \%userHash); $self->{packer}->addRootRole( $roleName, 0, \%rolePermsHash); } } sub getTrafficValue { my ( $self, $tableName, $whereCond ) = @_; my $trafficValue = ''; my $sql = "SELECT http_in, http_out, ftp_in, ftp_out, smtp_in, smtp_out, " . "pop3_imap_in, pop3_imap_out, date FROM $tableName WHERE $whereCond"; if ( $self->{dbh}->execute_rownum($sql) ) { my @keys = ( 'http', 'ftp', 'smtp', 'pop3-imap' ); my ( $key, $i, $ptrRow ); while ( $ptrRow = $self->{dbh}->fetchrow() ) { for ( $i = 0 ; $i < @keys * 2 ; ++$i ) { if ( $ptrRow->[$i] ) { $trafficValue .= $ptrRow->[8]; $trafficValue .= ' '; $trafficValue .= $keys[ $i / 2 ]; $trafficValue .= ' '; $trafficValue .= ( $i % 2 ? 'out' : 'in' ); $trafficValue .= ' '; $trafficValue .= $ptrRow->[$i]; $trafficValue .= "\n"; } } } } $self->{dbh}->finish(); return $trafficValue; } # # addDomainTraffic - add current traffic # # arguments: # $root - XML node to add traffic's nodes # $domainId - ID of domain # sub addDomainTraffic { my ( $self, $domainId ) = @_; my $trafficValue = ''; if ( PleskVersion::atLeast( 6, 0, 0 ) ) { $trafficValue = $self->getTrafficValue( 'DomainsTraffic', "dom_id=$domainId" ); } else { my $sql = "SELECT transfer, date FROM stat WHERE dom_id=$domainId"; if ( $self->{dbh}->execute_rownum($sql) ) { my $ptrRow; while ( $ptrRow = $self->{dbh}->fetchrow() ) { if ( $ptrRow->[0] ) { $trafficValue .= $ptrRow->[1]; $trafficValue .= ' http in '; $trafficValue .= $ptrRow->[0]; $trafficValue .= "\n"; } } } $self->{dbh}->finish(); } $self->{packer}->setDomainTraffic( $domainId, $trafficValue ) if $trafficValue; } sub addClientTraffic { my ( $self, $clientId ) = @_; my $trafficValue = ''; if ( PleskVersion::atLeast( 6, 0, 0 ) ) { $trafficValue = $self->getTrafficValue( 'ClientsTraffic', "cl_id=$clientId" ); $self->{packer}->setClientTraffic( $clientId, $trafficValue ) if $trafficValue; } } # There are 3 types of nonexistent user mail handling: # Bounce with message (bounce:message text) # Catch to address (email@address) # SMTP reject (reject) # Returns bounce|catch|reject or empty string sub getNonexistentMode { my ( $self, $domainId ) = @_; my $sql = "SELECT p.value FROM Parameters p, DomainServices ds " . "WHERE ds.parameters_id = p.id AND ds.dom_id = $domainId AND p.parameter = 'nonexist_mail'"; my $mode; if ( $self->{dbh}->execute_rownum($sql) ) { if (my $rowPtr = $self->{dbh}->fetchrow()) { $mode = @{ $rowPtr }[0]; } } else { $mode = "bounce:This address no longer accepts mail."; } $self->{dbh}->finish(); return $mode; } sub getCatchAllAddress { my ( $self, $domainId ) = @_; my $sql; if ( PleskVersion::atLeast( 6, 0, 0 ) ) { my $mode = $self->getNonexistentMode($domainId); if ( $mode =~ /^catch$/ ) { $sql = "SELECT p.value FROM Parameters p, DomainServices ds " . "WHERE ds.parameters_id = p.id AND ds.dom_id = $domainId AND p.parameter = 'catch_addr'"; } elsif ( $mode =~ /^bounce$/ ) { $sql = "SELECT CONCAT('bounce:', p.value) FROM Parameters p, DomainServices ds " . "WHERE ds.parameters_id = p.id AND ds.dom_id = $domainId AND p.parameter = 'bounce_mess'"; } elsif ( $mode =~ /^reject$/ ) { $sql = "SELECT 'reject'"; } } elsif ( PleskVersion::atLeast( 5, 0, 0 ) ) { $sql = "SELECT p.value FROM Parameters p, dom_param dp WHERE " . "dp.dom_id = $domainId AND dp.param='param_id' AND dp.val = p.id AND p.parameter = 'catch_addr'"; } else { $sql = "SELECT dp.val FROM dom_param dp WHERE dp.dom_id = $domainId AND dp.param = 'catch_addr'"; } # some not supported mode or default parameter [bug 43901] return unless ($sql); if ( $self->{dbh}->execute_rownum($sql) ) { if ( my $rowPtr = $self->{dbh}->fetchrow() ) { my $catchAllAddr = @{ $rowPtr }[0]; if ($catchAllAddr) { $self->{packer}->setDomainCatchMail( $domainId, $catchAllAddr ); } } } $self->{dbh}->finish(); } # # makeMailListNode # # arguments: # $mlistId - ID of the mail list # $mlistName - name # $mllistState - state of maillist # # return: # $root - XML node # sub makeMailListNode { my ( $self, $domainId, $mlistId, $mlistName, $mlistState ) = @_; unless ( defined Mailman::version() ) { Packer::printToLog("Unable to found Mailman installation"); return; } my @owners = Mailman::getListOwners($mlistName); if ( !@owners ) { Packer::printToLog("Bad maillist $mlistName, skipped"); return; } my %listMembers = Mailman::getListMembers($mlistName); my $archiveDir = AgentConfig::get("MAILMAN_VAR_D") . "/archives/private/$mlistName.mbox"; $self->{packer}->addDomainMailList( $domainId, $mlistName, Mailman::getListPassword($mlistName), $mlistState, \@owners, \%listMembers, $archiveDir, "$mlistName.mbox" ); } sub makeCertificateNode { my ( $self, $certId, $parent, $parentType, $default ) = @_; my $proc; if ( 'server' eq $parentType ) { $proc = $self->getSubroutineRef("addServerCertificate"); } elsif ( 'domain' eq $parentType ) { $proc = $self->getSubroutineRef("addDomainCertificate"); } else { Packer::printToError('Error: makeCertificateNode: unexpected parent type'); return; } my ( $sql, %cert, $item ); $sql = "SELECT * FROM certificates WHERE id=$certId"; unless ( $self->{dbh}->execute_rownum($sql) ) { $self->{dbh}->finish(); &Packer::printToError( "Error: makeCertificateNode: certificate ID '$certId' is not found"); return undef; } if ( my $hashPtr = $self->{dbh}->fetchhash() ) { %cert = %{ $hashPtr }; } $self->{dbh}->finish(); my $cert; my $csr; my $ca_cert; my $name; if ( PleskVersion::atLeast( 6, 0, 0 ) ) { $cert = $cert{'cert'}; $csr = $cert{'csr'}; $ca_cert = $cert{'ca_cert'}; } elsif ( PleskVersion::atLeast( 5, 0, 0 ) ) { $cert = $cert{'pub_key'}; } if ( PleskVersion::atLeast( 6, 0, 0 ) ) { $name = $cert{'name'}; } else { # certificate names were not used in Plesk prior to 6.0 $name = $certId; } my $pvt_key = $cert{'pvt_key'}; if ( 'server' eq $parentType ) { $self->{packer}->$proc( $name, $cert, $csr, $ca_cert, $pvt_key, $default ); } else { $self->{packer}->$proc( $parent, $name, $cert, $csr, $ca_cert, $pvt_key, $default ); } } sub makeDatabaseNode { my ( $self, $dbId, $parent, $parentType, $sappId, $sappResource ) = @_; my ( $ptrHash, $ptrRow, $item, $charset, $dbServerId, $dbServerHost, $dbServerPort ); my $proc; if( $sappId ){ if ( 'domain' eq $parentType ) { $proc = $self->getSubroutineRef("addDomainSappDatabase");; } elsif ( 'subdomain' eq $parentType ) { $proc = $self->getSubroutineRef("addSubDomainSappDatabase"); } else { Packer::printToError( "Error: makeDatabaseNode: Unexpected type of parent \"$parentType\""); return; } } else{ if ( 'domain' eq $parentType ) { $proc = $self->getSubroutineRef("addDomainDatabase"); } else { Packer::printToError( "Error: makeDatabaseNode: Unexpected type of parent \"$parentType\""); return; } } my $sql = "SELECT name, type FROM data_bases WHERE id=$dbId"; unless ( ( $self->{dbh}->execute_rownum($sql) ) && ( $ptrRow = $self->{dbh}->fetchrow() ) ) { $self->{dbh}->finish(); my $msg = "Broken referencial integrity: Database id $dbId is not found in data_bases"; print STDERR "$msg\n"; Packer::printToError( $msg ); return; } my ( $dbName, $dbType ) = @{ $ptrRow }; $self->{dbh}->finish(); if ( $dbType eq "postgres" or $dbType eq "postgresql" ) { $dbType = "postgresql"; } elsif ( $dbType ne "mysql" ) { Packer::printToError("Unknown database type: $dbType"); return; } my %dbServer; # Remote databases hosting was introduced in 8.0.0 if ( PleskVersion::atLeast( 8, 0, 0 ) ) { my $sql = "SELECT host,port,ds.type FROM DatabaseServers as ds, data_bases as db WHERE " . "ds.id = db.db_server_id AND db.id = $dbId"; if ( $self->{dbh}->execute_rownum($sql) ) { if( $ptrRow = $self->{dbh}->fetchrow() ) { $dbServerHost = ( $ptrRow->[0] ne 'localhost' ) ? $ptrRow->[0] : 'localhost'; $dbServerPort = $ptrRow->[1]; $dbServer{'type'} = $ptrRow->[2]; $dbServer{'host'} = "$ptrRow->[0]"; $dbServer{'port'} = "$ptrRow->[1]"; } } $self->{dbh}->finish(); } my @dbUsers; my %optional; $optional{'sapp-param'} = $sappResource if ($sappResource); my %contentDescription; if ( !$self->{shallow_dump} ) { Packer::printToLog("Database $dbName"); if ( PleskVersion::atLeast( 7, 5, 0 ) ) { $sql = "SELECT db_users.id, login, password, type FROM db_users, accounts WHERE " . "db_users.db_id = $dbId AND db_users.account_id = accounts.id"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( $ptrHash = $self->{dbh}->fetchhash() ) { $ptrHash->{'password'} ||= ''; # NULL -> '' my %item; $item{'login'} = $ptrHash->{'login'}; $item{'password'} = $ptrHash->{'password'}; $item{'type'} = $self->{packer}->normalizePasswordType( $ptrHash->{'type'} ); $item{'id'} = $ptrHash->{'id'}; push @dbUsers, \%item; } } } else { if ( $self->{dbh}->execute_rownum( "SELECT login, passwd FROM db_users WHERE db_id = $dbId") ) { while ( $ptrHash = $self->{dbh}->fetchhash() ) { my $dbPasswdType; # In Plesk 7.1.5 DB password type wasn't described in the DB. We # can distinguish the type only using length of password. if ( length( $ptrHash->{'passwd'} ) > 14 ) { $dbPasswdType = 'encrypted'; } else { $dbPasswdType = 'plain'; } if ( !defined $ptrHash->{'passwd'} ) { $ptrHash->{'passwd'} = ''; } my %item; $item{'login'} = $ptrHash->{'login'}; $item{'password'} = $ptrHash->{'passwd'}; $item{'type'} = $dbPasswdType; push @dbUsers, \%item; } } } $self->{dbh}->finish(); my ( $dbUser, $dbPasswd, $plesk_7 ); # remote database hosting regularizes the database connectivity even for local hosts. # thanks goes to xman. if ( PleskVersion::atLeast( 8, 0, 0 ) ) { my $sql = "SELECT admin_login, admin_password, ds.id FROM DatabaseServers as ds, data_bases as db " . "WHERE ds.id = db.db_server_id AND db.id = $dbId"; unless ( ( $self->{dbh}->execute_rownum($sql) ) && ( $ptrRow = $self->{dbh}->fetchrow() ) ) { $self->{dbh}->finish(); my $msg = "Broken referencial integrity: DatabaseServers vs data_bases for db id $dbId"; print STDERR "$msg\n"; Packer::printToError( $msg ); return; } ( $dbUser, $dbPasswd, $dbServerId ) = @{ $ptrRow }; $self->{dbh}->finish(); if ( $dbType eq "mysql" and $dbServerHost eq 'localhost' ) { $dbPasswd = AgentConfig::get('password'); } if ( $dbType eq "postgresql" ) { $optional{'version'} = getPostgresqlVersion(); } } else { $dbServerId = $dbType; if ( $dbType eq "mysql" ) { $dbUser = 'admin'; $dbPasswd = AgentConfig::get('password'); } else { $sql = "SELECT param, val FROM misc WHERE param RLIKE '^postgresql_admin_'"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( $ptrRow = $self->{dbh}->fetchrow() ) { my ( $name, $value ) = @{$ptrRow}; $dbUser = $value if $name =~ /login$/; $dbPasswd = $value if $name =~ /passwd$/; } } $self->{dbh}->finish(); $plesk_7 = 1; } } if ( $dbType eq "mysql" ) { $optional{'version'} = Db::MysqlUtils::getVersion(); } %contentDescription = ( "name" => $dbName, "type" => $dbType, "user" => $dbUser, "password" => $dbPasswd, "host" => $dbServerHost, "port" => $dbServerPort, "plesk_7" => $plesk_7 ); if ( $dbType eq "postgresql" ) { my $psql = AgentConfig::psqlBin(); #[Bug 119082] #$charset = `PGUSER=$dbUser PGPASSWORD='$dbPasswd' $psql -l template1 | grep '^[ \t]*$dbName ' | awk '{print \$5}'`; my $wrapPgsql = Packer::getDbConnect( $dbType, $dbUser, $dbPasswd, $dbName, $dbServerHost, undef, undef, undef, undef, $dbServerPort ); if ( ref($wrapPgsql) eq 'HASH' ) { if ( $wrapPgsql->{'EXECUTE'}->( "select pg_catalog.pg_encoding_to_char(d.encoding) FROM pg_catalog.pg_database d where d.datname='$dbName'" ) ) { my $ptrRow; if ( ( $ptrRow = $wrapPgsql->{'FETCHROW'}->() ) ) { $charset = $ptrRow->[0]; if ( $charset ne '' ) { $optional{'charset'} = $charset; } } $wrapPgsql->{'FINISH'}->(); } } else { Packer::printToLog( "Cannot connect to postgresql $dbServerHost:$dbServerPort (database '$dbName')" ); } } if ( $dbType eq "mysql" ) { my $wrapMysql = Packer::getDbConnect( $dbType, $dbUser, $dbPasswd, $dbName, $dbServerHost, undef, undef, undef, undef, $dbServerPort ); if ( ref($wrapMysql) eq 'HASH' ) { if ( $wrapMysql->{'EXECUTE'}->("SHOW VARIABLES LIKE \"character_set_database\"") ) { my $ptrRow = $wrapMysql->{'FETCHROW'}->(); my $charset = $ptrRow->[1] if $ptrRow; $optional{'charset'} = $charset if $charset; $wrapMysql->{'FINISH'}->(); } } } } if( $sappId ){ $self->{packer}->$proc( $dbId, $dbServerId, $parent, $sappId, $dbName, $dbType, \%optional, \%dbServer, \@dbUsers, \%contentDescription ); } else{ $self->{packer}->$proc( $dbId, $dbServerId, $parent, $dbName, $dbType, \%optional, \%dbServer, \@dbUsers, \%contentDescription ); } } # # makeMailUserNode # # argumets: # $mailId - mail ID # $passwd - password # $typePasswd - type of password # $domainName - name of domain # # return: # $root = XML node 'mailuser' # sub makeMailUserNode { my ( $self, $domainId, $mailId, $passwd, $typePasswd, $domainName, $domainAsciiName, $parentType, $clientId ) = @_; my ( $sql, %mail, $item, $ptrRow, $ptrHash, $dir, $id, $mbox_quota, %mailParams ); $sql = "SELECT * FROM mail WHERE id = $mailId"; unless ( ( $self->{dbh}->execute_rownum($sql) ) && ( $ptrHash = $self->{dbh}->fetchhash() ) ) { $self->{dbh}->finish(); my $msg = "Broken referencial integrity: Mail id $mailId is not found in mail"; print STDERR "$msg\n"; Packer::printToError( $msg ); return; } %mail = %{ $ptrHash }; $self->{dbh}->finish(); my $mailName = $mail{'mail_name'}; my $userUid = undef; if (exists $mail{'userId'} and $mail{'userId'} != 0) { $sql = "SELECT uuid FROM smb_users WHERE id = $mail{'userId'}"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( $ptrRow = $self->{dbh}->fetchrow() ) { $userUid = $ptrRow->[0]; } } $self->{dbh}->finish(); } $self->{packer}->addMail( $domainId, $mailId, $mailName, $passwd, $typePasswd, $userUid ); if ( PleskVersion::atLeast( 6, 0, 0 ) ) { $sql = "SELECT param,val FROM mn_param WHERE mn_id=$mailId"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( $ptrRow = $self->{dbh}->fetchrow() ) { $mailParams{ $ptrRow->[0] } = $ptrRow->[1]; } } $self->{dbh}->finish(); } unless ( PleskVersion::atLeast(10, 0, 0) ) { if( defined $parentType && defined $clientId ) { my ( $access, $antispam, $antivirus ); if ( defined $mail{'perm_id'} ) { $sql = "SELECT permission FROM Permissions WHERE id = $mail{'perm_id'} AND value='true'"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( $ptrRow = $self->{dbh}->fetchrow() ) { if ( $ptrRow->[0] eq 'cp_access') { $access = 1; } elsif ( $ptrRow->[0] eq 'manage_spamfilter' ) { $antispam = 1; } elsif ( $ptrRow->[0] eq 'manage_virusfilter' ) { $antivirus = 1; } } if ( $access ) { $self->makeMailAccessUserRole($mailName, $domainName, $passwd, $typePasswd, $parentType, $clientId, $antispam, $antivirus); } } $self->{dbh}->finish(); } elsif ( defined( $mail{'cp_access'} ) ) { $self->makeMailAccessUserRole($mailName, $domainName, $passwd, $typePasswd, $parentType, $clientId ); } } } if ( $mail{'mbox_quota'} ) { $mbox_quota = $mail{'mbox_quota'}; if ( !PleskVersion::atLeast( 6, 0, 0 ) and $mbox_quota ne "-1" ) { $mbox_quota = $mbox_quota * 1024; } $self->{packer}->setMailBoxQuota( $mailId, $mbox_quota ); } my $enable_mailbox = $mail{'postbox'} =~ /true/; # Check whether there autoresponder with attach # On 'Olde Pleskes' there was bug allowing attaches # when mailbox in turned off, so we have to explicitly # turn mailbox on if there is attach. $sql = "SELECT COUNT(ra.filename) FROM mail_resp AS mr, resp_attach as ra " . "WHERE ra.rn_id = mr.id AND mr.mn_id = $mailId"; if ( $self->{dbh}->execute_rownum($sql) and ( $ptrRow = $self->{dbh}->fetchrow() ) and $ptrRow->[0] != 0 ) { $enable_mailbox = 1; } $self->{dbh}->finish(); if ($enable_mailbox) { $dir = getPleskMailnamesDir() . "/$domainAsciiName/$mailName/Maildir"; $self->{packer}->setMailBox( $mailId, $mailName, $domainAsciiName, ( $mail{'postbox'} =~ /true/ ? 'true' : 'false' ), $dir ); } # # aliases # if ( PleskVersion::atLeast( 5, 0, 0 ) ) { $sql = "SELECT alias FROM mail_aliases WHERE mn_id=$mailId"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( $ptrRow = $self->{dbh}->fetchrow() ) { $self->{packer}->addMailAliase( $mailId, $ptrRow->[0] ); } } $self->{dbh}->finish(); } # # end aliases # # # mail forwarding # my @members; $sql = "SELECT address FROM mail_redir WHERE mn_id=$mailId"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( $ptrRow = $self->{dbh}->fetchrow() ) { if ( $ptrRow->[0] ne $mailName . "@" . $domainName ) { push @members, $ptrRow->[0]; } } } $self->{dbh}->finish(); my $forwarding_enabled = ($mail{'mail_group'} eq 'true'); unless ( PleskVersion::atLeast( 10, 0, 0 ) and not PleskVersion::isSmb() ) { if ( $mail{'redir_addr'} ) { push @members, $mail{'redir_addr'}; } $forwarding_enabled = $forwarding_enabled || ($mail{'redirect'} eq 'true'); } $self->{packer}->setMailForwarding( $mailId, $forwarding_enabled, \@members ); # # end mail forwarding # # # autoresponders # $dir = getPleskMailnamesDir() . "/$domainAsciiName/$mailName/\@attachments"; my (@autos); $sql = "SELECT id FROM mail_resp WHERE mn_id=$mailId ORDER BY id"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( $ptrRow = $self->{dbh}->fetchrow() ) { push @autos, $ptrRow->[0]; } } $self->{dbh}->finish(); my %attaches; my @autoresponders; foreach $id (@autos) { my %item = makeAutoresponderNode( $self, $id, $mailName . "@" . $domainName ); push @autoresponders, \%item; } my @filelist; my $util = AgentConfig::get("PRODUCT_ROOT_D") . "/admin/sbin/"; if ( PleskVersion::atLeast( 6, 5, 0 ) ) { my $mn = $mailName; $mn =~ s/\&/\\&/g; $util .= "mailmng --list-attachments --domain-name=$domainName --mailname=$mn"; } else { $util .= "list_files -1A '" . getPleskMailnamesDir() . "/$domainAsciiName/$mailName/\@attachments/'"; } my @filelist; open( LIST, "$util |" ); while () { chomp; my ($file) = split /\t/; push @filelist, $file; } #clear list if utility failed unless ( close(LIST) ) { @filelist = (); } # Old Plesk utilities printed return code on stdout (#66905) unless ( PleskVersion::atLeast( 7, 1, 0 ) ) { if ( $#filelist != -1 && $filelist[$#filelist] =~ /^\d$/ ) { $#filelist -= 1; } } $self->{packer}->setMailAutoresponders( $mailId, $mailName, $domainAsciiName, $dir, $mail{'autoresponder'}, \@autoresponders, \@filelist ); # # end autoresponders # # # Addressbook # if ( PleskVersion::atLeast( 6, 0, 0 ) ) { $self->makeAddressbookNode( $mailId, $mailName . '@' . $domainAsciiName ); } # # Spamassassin # if ( PleskVersion::atLeast( 7, 0, 0 ) ) { $dir = getPleskMailnamesDir() . "/$domainAsciiName/$mailName/.spamassassin"; $self->makeSpamassassinNode( $mailId, $mail{'mail_name'}, $domainAsciiName, $mail{'spamfilter'}, $dir ); } # # End Spamassassin # if ( PleskVersion::atLeast( 8, 1, 1 ) ) { if ( $mail{'virusfilter'} ne 'none' ) { my %states_map = ( 'incoming' => 'in', 'outgoing' => 'out', 'any' => 'inout' ); if ( defined( $states_map{ $mail{'virusfilter'} } ) ) { $self->{packer}->setMailVirusSettings( $mailId, $states_map{ $mail{'virusfilter'} } ); } } } # FIXME: why so crude check here? elsif ( -e "/etc/drweb/users.conf" ) { my $state = $self->makeDrwebNode( $mailName . '@' . $domainName ); $self->{packer}->setMailVirusSettings( $mailId, $state ) if (defined($state) and ($state ne 'none')); } } # # makeAutoresponderNode # # arguments: # $id - ID of autoreponder # # return: # $root - XML node #select * from clients; sub makeAutoresponderNode { my ( $self, $autoId, $mailName ) = @_; my ( $name, $value, $sql, %auto, $ptrRow, $item ); $sql = "SELECT * FROM mail_resp WHERE id=$autoId"; unless ( ( $self->{dbh}->execute_rownum($sql) ) && ( $ptrRow = $self->{dbh}->fetchhash() ) ) { $self->{dbh}->finish(); my $msg = "Broken referencial integrity: autoresponder id $autoId is not found in mail_resp"; print STDERR "$msg\n"; Packer::printToError( $msg ); return; } %auto = %{ $ptrRow }; $self->{dbh}->finish(); # # forward # $sql = "SELECT address FROM resp_forward WHERE rn_id=$autoId"; if ( $self->{dbh}->execute_rownum($sql) ) { my (@list); while ( $ptrRow = $self->{dbh}->fetchrow() ) { # skip empty entries - found somewhere @ the wild Net push @list, $ptrRow->[0] if $ptrRow->[0]; } if (@list) { $auto{'redirect'} = join( ',', @list ); } } $self->{dbh}->finish(); my @attach; $sql = "SELECT filename FROM resp_attach WHERE rn_id=$autoId"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( $ptrRow = $self->{dbh}->fetchrow() ) { push @attach, $ptrRow->[0]; } } $self->{dbh}->finish(); $auto{'attach'} = \@attach; return %auto; } sub makeAddressbookNode { my ( $self, $mailId, $mailName ) = @_; my @params; my $sql = "SELECT Db FROM mysql.db WHERE db='horde'"; unless( $self->{dbh}->execute_rownum($sql) ){ $self->{dbh}->finish(); return; } $self->{dbh}->finish(); $sql = "SHOW TABLES FROM horde LIKE 'turba_objects'"; unless( $self->{dbh}->execute_rownum($sql) ) { $self->{dbh}->finish(); return; } $self->{dbh}->finish(); my $ptrHash; $sql = "SELECT * FROM horde.turba_objects WHERE owner_id = '$mailName'"; if ($self->{dbh}->execute_rownum($sql) ) { while ( $ptrHash = $self->{dbh}->fetchhash() ) { push @params, $ptrHash; } } $self->{dbh}->finish(); $self->{packer}->setMailAddressbook( $mailId, \@params ); } sub getWebspaceId { my ( $self, $domainId) = @_; my $use_webspaces = PleskVersion::atLeast( 10, 0, 0 ) and not PleskVersion::isSmb(); return 0 unless $use_webspaces; my $www_root; my $webspace_id; my $sql = "SELECT webspace_id FROM domains WHERE id = $domainId"; if ( $self->{dbh}->execute_rownum($sql) and my $ptrRow = $self->{dbh}->fetchrow() ) { $webspace_id = $ptrRow->[0]; } $self->{dbh}->finish(); return $webspace_id; } sub getDomainWwwRoot { my ( $self, $domainId, $absolute) = @_; my $use_webspaces = PleskVersion::atLeast( 10, 0, 0 ) and not PleskVersion::isSmb(); if($use_webspaces){ my $www_root; my $sql = "SELECT www_root FROM hosting WHERE dom_id = $domainId"; if ( $self->{dbh}->execute_rownum($sql) and my $ptrRow = $self->{dbh}->fetchrow() ) { $www_root = $ptrRow->[0]; } $self->{dbh}->finish(); if($absolute) { return $www_root; } my $parentDomainName; my $webspace_id = $self->getWebspaceId($domainId); if($webspace_id) { $parentDomainName = PleskStructure::getDomainAsciiNameFromId($webspace_id); } else { $parentDomainName = PleskStructure::getDomainAsciiNameFromId($domainId); } my $parentDomainRoot = $self->getWebspaceRoot($parentDomainName); $www_root = substr($www_root,length($parentDomainRoot)); substr($www_root,0,1) = '' if substr($www_root,0,1) eq '/'; return $www_root; } else { return ($absolute? $self->getWebspaceRoot( PleskStructure::getDomainAsciiNameFromId($domainId) ) . '/' : '' ) .'httpdocs'; } } sub getSubDomainWwwRoot { my ( $self, $subdomainId, $absolute) = @_; my $domainId; my $subdomainName; my $sql = "SELECT dom_id, name FROM subdomains WHERE id = $subdomainId"; if ( $self->{dbh}->execute_rownum($sql) and my $ptrRow = $self->{dbh}->fetchrow() ) { $domainId = $ptrRow->[0]; $subdomainName = $ptrRow->[1]; } $self->{dbh}->finish(); my $use_webspaces = PleskVersion::atLeast( 10, 0, 0 ) and not PleskVersion::isSmb(); if($use_webspaces){ my $www_root; $sql = "SELECT www_root FROM subdomains WHERE id = $subdomainId"; if ( $self->{dbh}->execute_rownum($sql) and my $ptrRow = $self->{dbh}->fetchrow() ) { $www_root = $ptrRow->[0]; } $self->{dbh}->finish(); if($absolute) { return $www_root; } my $webspaceId = $self->getWebspaceId($domainId); $domainId = $webspaceId if $webspaceId; my $parentDomainRoot = $self->getWebspaceRoot( PleskStructure::getDomainAsciiNameFromId($domainId) ); $www_root = substr($www_root,length($parentDomainRoot)); substr($www_root,0,1) = '' if substr($www_root,0,1) eq '/'; return $www_root; } else { return ($absolute? $self->getWebspaceRoot( PleskStructure::getDomainAsciiNameFromId($domainId) ) . '/' : '' ) .'subdomains/' . $subdomainName . '/httpdocs'; } } sub getDomainCgiRoot { my ( $self, $domainId, $absolute) = @_; my $use_webspaces = PleskVersion::atLeast( 10, 0, 0 ) and not PleskVersion::isSmb(); if($use_webspaces){ my $parentDomainName; my $webspace_id = $self->getWebspaceId($domainId); if($webspace_id) { $parentDomainName = PleskStructure::getDomainAsciiNameFromId($webspace_id); } else { $parentDomainName = PleskStructure::getDomainAsciiNameFromId($domainId); } my $parentDomainRoot = $self->getWebspaceRoot($parentDomainName); my $cgi_bin_mode; my $sql = "SELECT val FROM dom_param WHERE dom_id = $domainId AND param = 'cgi_bin_mode'"; if ( $self->{dbh}->execute_rownum($sql) and my $ptrRow = $self->{dbh}->fetchrow() ) { $cgi_bin_mode = $ptrRow->[0]; } $self->{dbh}->finish(); my $www_root; my $cgi_root; if($cgi_bin_mode eq 'www-root') { $sql = "SELECT www_root FROM hosting WHERE dom_id = $domainId"; if ( $self->{dbh}->execute_rownum($sql) and my $ptrRow = $self->{dbh}->fetchrow() ) { $www_root = $ptrRow->[0]; } $self->{dbh}->finish(); $cgi_root = $www_root . '/cgi-bin'; } else { $cgi_root = $parentDomainRoot . '/cgi-bin'; } if($absolute) { return $cgi_root; } $cgi_root = substr($cgi_root,length($parentDomainRoot)); substr($cgi_root,0,1) = '' if substr($cgi_root,0,1) eq '/'; return $cgi_root; } else { return ($absolute? $self->getWebspaceRoot( PleskStructure::getDomainAsciiNameFromId($domainId) ) . '/' : '' ) .'cgi-bin'; } } sub getSubDomainCgiRoot { my ( $self, $subdomainId, $absolute) = @_; my $domainId; my $subdomainName; my $sql = "SELECT dom_id, name FROM subdomains WHERE id = $subdomainId"; if ( $self->{dbh}->execute_rownum($sql) and my $ptrRow = $self->{dbh}->fetchrow() ) { $domainId = $ptrRow->[0]; $subdomainName = $ptrRow->[1]; } $self->{dbh}->finish(); my $use_webspaces = PleskVersion::atLeast( 10, 0, 0 ) and not PleskVersion::isSmb(); if($use_webspaces){ my $webspaceId = $self->getWebspaceId($domainId); my $parentDomainRoot = $self->getWebspaceRoot( PleskStructure::getDomainAsciiNameFromId($webspaceId? $webspaceId : $domainId) ); my $cgi_bin_mode; $sql = "SELECT val FROM dom_param WHERE dom_id = $domainId AND param = 'cgi_bin_mode'"; if ( $self->{dbh}->execute_rownum($sql) and my $ptrRow = $self->{dbh}->fetchrow() ) { $cgi_bin_mode = $ptrRow->[0]; } $self->{dbh}->finish(); my $www_root; my $cgi_root; if($cgi_bin_mode eq 'www-root') { $sql = "SELECT www_root FROM subdomains WHERE id = $subdomainId"; if ( $self->{dbh}->execute_rownum($sql) and my $ptrRow = $self->{dbh}->fetchrow() ) { $www_root = $ptrRow->[0]; } $self->{dbh}->finish(); $cgi_root = $www_root . '/cgi-bin'; } else { if($webspaceId) { $cgi_root = $parentDomainRoot . '/cgi-bin'; } else { $cgi_root = $parentDomainRoot . '/subdomains/' . $subdomainName . '/cgi-bin'; } } if($absolute) { return $cgi_root; } $cgi_root = substr($cgi_root,length($parentDomainRoot)); substr($cgi_root,0,1) = '' if substr($cgi_root,0,1) eq '/'; return $cgi_root; } else { return ($absolute? $self->getWebspaceRoot( PleskStructure::getDomainAsciiNameFromId($domainId) ) . '/' : '' ) .'subdomains/' . $subdomainName . '/cgi-bin'; } } sub makePhostingNode { my ( $self, $ptrDomain, $ptrDomParams, $ptrSiteApplications, $is_site ) = @_; my @SiteApplications = @{$ptrSiteApplications}; unless ( ref($ptrDomain) =~ /HASH/ ) { &Packer::printToError("Error: makePhostNode: bad arguments"); return undef; } my ( $domainName, $domainRoot, $path, $sql, %hosting, $domainId, $xmlName, $fieldName, $id, $item, $ptrRow, $ptrHash ); $domainName = $ptrDomain->{'name'}; $domainId = $ptrDomain->{'id'}; my %hostingParams; $sql = "SELECT * FROM hosting WHERE dom_id=$domainId"; if ( ( $self->{dbh}->execute_rownum($sql) ) && ( $ptrHash = $self->{dbh}->fetchhash() ) ) { %hosting = %{ $ptrHash }; } $self->{dbh}->finish(); if ( defined( $hosting{'webstat'} ) and $hosting{'webstat'} ) { $hostingParams{'webstat'} = $hosting{'webstat'}; } if ( defined( $hosting{'ssl'} ) and $hosting{'ssl'} ) { $hostingParams{'https'} = $hosting{'ssl'}; } if ( PleskVersion::atLeast( 7, 5, 3 ) ) { if ( defined( $hosting{'same_ssl'} ) and ( $hosting{'same_ssl'} eq 'true' ) ) { $hostingParams{'shared-content'} = 'true'; } } $hostingParams{'www-root'} = $self->getDomainWwwRoot($domainId); $sql = "SELECT param, val FROM dom_param WHERE dom_id='$domainId' " . "AND ( param='apacheErrorDocs' OR param='cgi_bin_mode')"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( $ptrRow = $self->{dbh}->fetchrow() ) { if ($ptrRow->[0] eq 'apacheErrorDocs') { $hostingParams{'errdocs'} = 'true' if ($ptrRow->[1] eq 'true'); } elsif ($ptrRow->[0] eq 'cgi_bin_mode') { $hostingParams{'cgi_bin_mode'} = 'www-root' if ($ptrRow->[1] eq 'www-root'); } } } $self->{dbh}->finish(); if (defined( $hosting{'maintenance_mode'} )) { $hostingParams{'maintenance_mode'} = $hosting{'maintenance_mode'}; } my %sysuser; # # sysuser # Logging::info("Dumping system user"); if ( PleskVersion::atLeast( 5, 0, 0 ) ) { if ( $id = $hosting{'sys_user_id'} ) { %sysuser = $self->makePleskSysUserNode($id); $sysuser{'relative_path'} = $self->getDefaultWebspaceRoot( $domainName ); } } else { %sysuser = $self->makeSyntheticSysUserNode( $hosting{'login'}, $hosting{'passwd'}, 'plain' ); } # # end sysuser # my $domUser = lc( $sysuser{'login'} ); my %scripting; # # scripting # while ( ( $xmlName, $fieldName ) = each(%hostingScripting) ) { next if $fieldName =~ /asp_dot_net/; if ( defined( $hosting{$fieldName} ) ) { if ( $hosting{$fieldName} eq 'true' or $hosting{$fieldName} eq 'false' ) { $scripting{$xmlName} = $hosting{$fieldName}; } elsif ( $fieldName eq 'php_handler_type') { $scripting{$xmlName} = $hosting{$fieldName} if $hosting{$fieldName}; $scripting{$xmlName} = 'isapi' if $scripting{$xmlName} eq 'module'; } } } delete $scripting{'php_handler_type'} if exists $scripting{'php_handler_type'} and ( not exists $scripting{'php'} or $scripting{'php'} eq 'false'); # # end scripting # $hostingParams{'wu_script'} = 'true' if exists $ptrDomParams->{'wu_script'} && $ptrDomParams->{'wu_script'} eq 'true'; $hostingParams{'sitebuilder-site-id'} = $ptrDomParams->{'site_builder_site_id'} if exists $ptrDomParams->{'site_builder_site_id'}; if ( PleskVersion::atLeast( 10, 0, 0 ) and not PleskVersion::isSmb() ) { my $published = $self->{packer}->getSb5SitePublished($domainName); $hostingParams{'sitebuilder-site-published'} = $published if defined $published; } my @sites; if (PleskVersion::atLeast( 10, 0, 0 ) and not PleskVersion::isSmb()) { $sql = "SELECT name, displayName, id FROM domains WHERE webspace_id=$domainId"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( my $ptrHash = $self->{dbh}->fetchhash() ) { push @sites, { %{$ptrHash} }; } } $self->{dbh}->finish(); } if ( !$self->{only_mail_dump} ) { $self->{packer}->setDomainPhosting( $domainId, \%hostingParams, $is_site? undef: \%sysuser, \%scripting ); } else { if( @sites ) { $self->{packer}->setDomainPhostingEmpty( $domainId, $is_site? undef: \%sysuser ); } } if ( !$self->{only_mail_dump} ) { #----------------------------------------------------------------- # Site applications content should not be included into dump # together with other website content. #----------------------------------------------------------------- my @exclude_httpdocs_files; push @exclude_httpdocs_files, 'plesk-stat'; my @exclude_httpsdocs_files; push @exclude_httpsdocs_files, 'plesk-stat'; my @exclude_cgi_bin_files; foreach my $sapp (@SiteApplications) { next if !$sapp->isDomainSiteapp($domainName); if ( $sapp->isSsl() ) { push @exclude_httpsdocs_files, $sapp->getHtdocsFiles(); } else { push @exclude_httpdocs_files, $sapp->getHtdocsFiles(); } push @exclude_cgi_bin_files, $sapp->getCgibinFiles(); } # Hosting content dump my $webspaceId = $self->getWebspaceId($domainId); # used for Site content-related subs $domainRoot = $self->getDomainRoot($domainName); if ( -d $domainRoot and !$self->{configuration_dump} ) { my @exclude_vhost_files; my $httpdocsDir = $self->getDomainWwwRoot($domainId); push @exclude_vhost_files, "$httpdocsDir/plesk-stat"; if ( -d $domainRoot . "/httpsdocs") { push @exclude_vhost_files, "httpsdocs/plesk-stat"; } if(@sites) { foreach my $ptrHash (@sites) { my $siteHttpdocsDir = $self->getDomainWwwRoot($ptrHash->{'id'}); push @exclude_vhost_files, "$siteHttpdocsDir/plesk-stat"; } } $self->{packer}->setDomainPhostingFullContent( $domainId, $domainName, $domainRoot, { 'sysuser' => $domUser, 'exclude' => \@exclude_vhost_files } ) if $self->{dump_vhost}; } my $domainWwwRoot = $self->getDomainWwwRoot($domainId, 'absolute'); if ( -d $domainWwwRoot and !$self->{configuration_dump} ) { $self->{packer}->setDomainPhostingHttpdocsContent( $domainId, $domainName, $webspaceId? $webspaceId:$domainId, $domainWwwRoot, { 'sysuser' => $domUser, 'exclude' => \@exclude_httpdocs_files } ); } if ( -d $domainRoot . "/httpsdocs" and !$self->{configuration_dump} ) { $self->{packer}->setDomainPhostingHttpsdocsContent( $domainId, $domainName, "$domainRoot/httpsdocs", { 'sysuser' => $domUser, 'exclude' => \@exclude_httpsdocs_files } ); } my $domainCgiRoot = $self->getDomainCgiRoot($domainId, 'absolute'); if ( -d $domainCgiRoot and !$self->{configuration_dump} ) { $self->{packer}->setDomainPhostingCgibinContent( $domainId, $domainName, $webspaceId? $webspaceId:$domainId, $domainCgiRoot, { 'sysuser' => $domUser, 'exclude' => \@exclude_cgi_bin_files } ); } if ( -d $domainRoot and !$self->{configuration_dump} ) { $self->{packer}->setDomainPhostingStatisticsContent( $domainId, $domainName, "$domainRoot/statistics" ) if $self->{dump_vhost}; my $webstatRoot = ( PleskVersion::atLeast( 5, 0, 0 ) ) ? $domainRoot . "/statistics/webstat" : $domainRoot . "/httpdocs/webstat"; $self->{packer}->setDomainPhostingWebstatContent( $domainId, $domainName, $webstatRoot ); $self->{packer}->setDomainPhostingWebstatSslContent( $domainId, $domainName,"$domainRoot/statistics/webstat-ssl" ); $self->{packer}->setDomainPhostingFtpstatContent( $domainId, $domainName, "$domainRoot/statistics/ftpstat" ); $self->{packer}->setDomainPhostingLogsContent( $domainId, $domainName, "$domainRoot/statistics/logs" ) unless $self->{skip_logs}; $self->{packer}->setDomainPhostingAnonFtpstatContent( $domainId, $domainName, "$domainRoot/statistics/anon_ftpstat" ); $self->{packer}->setDomainPhostingErrdocsContent( $domainId, $domainName, "$domainRoot/error_docs", { 'sysuser' => $domUser } ); $self->{packer}->setDomainPhostingPrivateContent( $domainId, $domainName, "$domainRoot/private", { 'sysuser' => $domUser } ); if (PleskVersion::isSmb()) { $self->{packer}->setSappScriptsContentToPhosting($domainId, "$domainRoot/vault_scripts", "$domainRoot/vault_https_scripts"); } } if ( PleskVersion::atLeast( 10, 0, 0 ) and not PleskVersion::isSmb() ) { if ( !$self->{configuration_dump} and !$self->{only_mail_dump} ) { $self->addSb5DomainContent( $domainId, $domainName, $ptrDomParams->{'site_builder_site_id'}); } else { Packer::printToLog("Skip domain sitebuilder content dumping due to settings"); } } #----------------------------------------------------------------- # Dump of installed site applications #----------------------------------------------------------------- foreach my $sapp (@SiteApplications) { if ( !$sapp->isDomainSiteapp($domainName) ) { next; } $self->dumpSiteApplication( $sapp, $domainRoot, $domainWwwRoot, $domainCgiRoot, $domainId, 'domain', $webspaceId); } unless ($is_site) { # # frontpage user # if ( exists $hosting{'fp_adm'} and $hosting{'fp_adm'} ) { $self->{packer}->setDomainFrontPageAdmin( $domainId, $hosting{'fp_adm'}, $hosting{'fp_pass'}, 'plain' ); } elsif ( exists $hosting{'fp'} and $hosting{'fp'} eq 'true' and !$hosting{'fp_adm'} and !$hosting{'fp_pass'} ) { # Workaround for older Plesks: during upgrade 1.3 -> 2.0 (or something) # frontpage administrator records were lost my ( $fp_adm, $fp_pass, $fp_pass_type ); if ( PleskVersion::atLeast( 5, 0, 0 ) ) { my %sysuser = $self->getSysUserInfo( $hosting{'sys_user_id'} ); $fp_adm = lc( $sysuser{'login'} ); if ( PleskVersion::atLeast( 6, 0, 0 ) ) { ($fp_pass, $fp_pass_type ) = $self->makeAccountPasswordNode( $sysuser{'account_id'} ); } else { $fp_pass = $sysuser{'passwd'}; $fp_pass_type = 'plain'; } } else { $fp_adm = $hosting{'login'}; $fp_pass = $hosting{'login'}; $fp_pass_type = 'plain'; } $self->{packer}->setDomainFrontPageAdmin( $domainId, $fp_adm, $fp_pass, $fp_pass_type ); } # # end frontpage user # } $self->makeDomainLogrotationNode($domainId); $self->addAnonFtp( $domainId, $domainName, { 'sysuser' => $domUser } ); # # protected dirs # if ( PleskVersion::atLeast( 10, 0, 0 ) and not PleskVersion::isSmb() ) { $sql = "SELECT id, path, realm, non_ssl, cgi_bin, `ssl` FROM protected_dirs WHERE dom_id=$domainId ORDER BY id"; if ( $self->{dbh}->execute_rownum($sql) ) { my (@dirs); while ( $ptrRow = $self->{dbh}->fetchrow() ) { push @dirs, [ @{$ptrRow} ]; } foreach $ptrRow (@dirs) { my $pdirId = $ptrRow->[0]; my $pdirPath = $ptrRow->[1]; my $pdirTitle = $ptrRow->[2]; my $pdirNonSSL = $ptrRow->[3]; my $pdirCGI = $ptrRow->[4]; my $pdirSSL = $ptrRow->[5]; $item = $self->makeProtDirNode( $domainId, $pdirId, $pdirPath, $pdirTitle, $pdirNonSSL, $pdirSSL, $pdirCGI); } } $self->{dbh}->finish(); } else { if ( PleskVersion::atLeast( 8, 0, 0 ) ) { $sql = "SELECT id,path,realm,non_ssl,`ssl`,cgi_bin FROM protected_dirs WHERE dom_id=$domainId ORDER BY id"; } elsif ( PleskVersion::atLeast( 6, 0, 0 ) ) { $sql = "SELECT id,path,realm,non_ssl,`ssl` FROM protected_dirs WHERE dom_id=$domainId ORDER BY id"; } else { $sql = "SELECT id,path,realm FROM protected_dirs WHERE dom_id=$domainId ORDER BY id"; } if ( $self->{dbh}->execute_rownum($sql) ) { my (@dirs); while ( $ptrRow = $self->{dbh}->fetchrow() ) { push @dirs, [ @{$ptrRow} ]; } foreach $ptrRow (@dirs) { unless ( defined( $hosting{'ssl'} ) and $hosting{'ssl'} =~ /true/ ) { $ptrRow->[4] = 'false'; # bug 97159 } $item = $self->makeProtDirNode( $domainId, @{$ptrRow} ); } } $self->{dbh}->finish(); } # # end protected dirs # unless ($is_site) { # # web users # $sql = "SELECT * FROM web_users WHERE dom_id=$domainId ORDER BY id"; if ( $self->{dbh}->execute_rownum($sql) ) { my (@webs); while ( $ptrHash = $self->{dbh}->fetchhash() ) { push @webs, { %{$ptrHash} }; } $self->{dbh}->finish(); foreach $ptrHash (@webs) { $self->makeWebUserNode( $ptrHash, $domainId, $domainName ); } } else { $self->{dbh}->finish(); } # # end web users # } unless ($is_site) { # # ftpusers # if ( PleskVersion::atLeast(10, 0, 0) ) { $sql = "SELECT * FROM ftp_users WHERE dom_id=$domainId"; if ( $self->{dbh}->execute_rownum($sql) ) { my (@ftps); while ( $ptrHash = $self->{dbh}->fetchhash() ) { push @ftps, { %{$ptrHash} }; } $self->{dbh}->finish(); foreach $ptrHash (@ftps) { $self->makeSubFtpUserNode( $ptrHash, $domainId, $domainName ); } } else { $self->{dbh}->finish(); } } # # end ftpusers # } # # subdomains # if ( PleskVersion::atLeast( 7, 0, 0 ) ) { $sql = "SELECT * FROM subdomains WHERE dom_id=$domainId ORDER BY id"; my (@subdoms); if ( $self->{dbh}->execute_rownum($sql) ) { while ( $ptrHash = $self->{dbh}->fetchhash() ) { push @subdoms, { %{$ptrHash} }; } } $self->{dbh}->finish(); foreach $ptrHash (@subdoms) { $ptrHash->{'www-root'} = $self->getSubDomainWwwRoot($ptrHash->{'id'}); $self->dumpSubDomain( $domainId, $ptrHash, $domainName, \@SiteApplications ); } } # # end subdomains # } if(@sites) { foreach my $ptrHash (@sites) { $self->makeSiteNode($ptrHash->{'name'},$ptrHash->{'displayName'} ); } } if ( !$self->{only_mail_dump} ) { # # configuration files (conf/vhost[_ssl].conf) # $domainRoot = $self->getDomainRoot($domainName); my $confDir = $domainRoot . '/conf/'; my $vhostConf = 'vhost.conf'; my $vhostSslConf = 'vhost_ssl.conf'; my @confFiles; push @confFiles, $vhostConf if ( -f $confDir . $vhostConf ); push @confFiles, $vhostSslConf if ( -f $confDir . $vhostSslConf ); $self->{packer}->setDomainPhostingConfContent( $domainId, $domainName, $confDir, { 'include' => \@confFiles } ); # # end configuration files (conf/vhost[_ssl].conf) # # # Webalizer configuration # my ( $directRef, @hiddenRefs, @groupRefs ); if ( PleskVersion::atLeast( 7, 5, 3 ) ) { my $sql = "SELECT referrer FROM webalizer_hidden_referrer " . " WHERE dom_id=$domainId"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( $ptrRow = $self->{dbh}->fetchrow() ) { if ( $ptrRow->[0] eq "Direct Request" ) { $directRef = 'true'; } else { push @hiddenRefs, $ptrRow->[0]; } } } $self->{dbh}->finish(); $sql = "SELECT referrer, group_name FROM webalizer_group_referrer " . " WHERE dom_id=$domainId"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( $ptrRow = $self->{dbh}->fetchrow() ) { push @groupRefs, { 'ref' => $ptrRow->[0], 'name' => $ptrRow->[1] }; } } $self->{dbh}->finish(); $self->{packer}->setDomainWebalizer( $domainId, $directRef, \@hiddenRefs, \@groupRefs ); } # # SiteBuilder connfiguration # if ( PleskVersion::atLeast( 8, 3, 0 ) ) { unless ( PleskVersion::atLeast( 10, 0, 0 ) and not PleskVersion::isSmb() ) { $self->makeDomainSiteBuilderNode($domainId); } } # # Perfomance # if ( ( defined( $hosting{'max_connection'} ) and $hosting{'max_connection'} ) or ( defined( $hosting{'traffic_bandwidth'} ) and $hosting{'traffic_bandwidth'} ) ) { $self->{packer}->setDomainPerfomance( $domainId, $hosting{'max_connection'}, $hosting{'traffic_bandwidth'} ); } if( exists $ptrDomParams->{'stat_ttl'} ){ $self->{packer}->setDomainWebStat( $domainId, $ptrDomParams->{'stat_ttl'} ); } } } sub makeDomainSiteBuilderNode () { my ( $self, $domainId ) = @_; my $sql = "SELECT sb_site_id, sb_siteowner_id, sb_siteowner_login FROM SBSites WHERE virtualHost_id = '$domainId'"; my $enabled = 'false'; my @sbSites; if ( $self->{dbh}->execute_rownum($sql) ) { while ( my $ptrHash = $self->{dbh}->fetchhash() ) { push @sbSites, $ptrHash; $enabled = 'true'; } } $self->{packer}->setDomainSitebuilder( $domainId, \@sbSites, $enabled ); $self->{dbh}->finish(); } #----------------------------------------------------------------- # Returns XmlNode of sapp-installed type or false #----------------------------------------------------------------- sub dumpSiteApplication( $ $ $ $ ) { my ( $self, $sapp, $vhost_path, $httpdocs_path, $cgibin_path, $parent, $parentType, $webspaceId ) = @_; my $proc = undef; if ( 'domain' eq $parentType ) { $proc = $self->getSubroutineRef("addDomainSapp"); } elsif ( 'subdomain' eq $parentType ) { $proc = $self->getSubroutineRef("addSubDomainSapp"); } else { Packer::printToError( "Error: dumpSiteApplication: Unexpected type of parent \"$parentType\""); } my $sapp_id = "$parentType:$parent:" . $sapp->getInstallPrefix(); my $prefix = $sapp->getInstallPrefix(); my $licenseType; if ( PleskVersion::atLeast( 8, 3, 0 ) ) { $licenseType = $sapp->getAPSClientItemLicenseType(); } $self->{packer}->$proc( $parent, $sapp_id, $sapp->getName(), $sapp->getVersion(), $sapp->getRelease(), $sapp->getDescription(), $sapp->isCommercial(), $sapp->isIntegrated(), $prefix, $sapp->isSsl(), $licenseType ); $self->{packer}->setSappParams( $sapp_id, $sapp ); #----------------------------------------------------------------- # Linked resources #----------------------------------------------------------------- # Databases foreach my $row ( $sapp->getDatabases() ) { $self->makeDatabaseNode( $row->{'id'}, $parent, $parentType, $sapp_id, $row->{'param'} ); } # Custom buttons foreach my $row ( $sapp->getCustomButtons() ) { $self->getCustomButtonById71( $row->{'id'}, $parent, $parentType, $sapp_id ); #if ( ref($cb) =~ /XmlNode/ ) { # $sapp_installed->{'ADDCHILD'}->($cb); # push @{ $self->{skip_custom_buttons} }, $row->{'id'}; #} } $self->{packer}->makeSiteAppInstalled( $sapp_id, $prefix, $sapp->isSsl() ); if (PleskVersion::atLeast(10, 0, 0) and not PleskVersion::isSmb()) { $self->{packer}->setSappEntryPoints( $sapp_id, $sapp); } #----------------------------------------------------------------- # Site application content #----------------------------------------------------------------- # sapp-scripts { if ( 'domain' eq $parentType ) { $proc = $self->getSubroutineRef("setDomainSappScriptsContent"); } elsif ( 'subdomain' eq $parentType ) { $proc = $self->getSubroutineRef("setSubDomainSappScriptsContent"); } $self->{packer}->$proc( $parent, $sapp_id, "$vhost_path/vault_scripts/$prefix", "$vhost_path/vault_https_scripts/$prefix" ); } # cgi-bin { if ( 'domain' eq $parentType ) { $proc = $self->getSubroutineRef("setDomainSappCgibinContent"); } elsif ( 'subdomain' eq $parentType ) { $proc = $self->getSubroutineRef("setSubDomainSappCgibinContent"); } $self->{packer}->$proc( $parent, $sapp_id, $cgibin_path . '/' . $prefix, $sapp->{cgi_bin}, $webspaceId ); } # htdocs my $htdocs_dir; my $use_webspaces = PleskVersion::atLeast( 10, 0, 0 ) and not PleskVersion::isSmb(); if($use_webspaces) { $htdocs_dir = $httpdocs_path . '/' . $prefix; } else { $htdocs_dir = $vhost_path . ( $sapp->isSsl() ? "/httpsdocs/" : "/httpdocs/" ) . $prefix; } # add '.htpasswd' files to dump, bug 93109 my ( $file, %files ); if (defined $self->{htdocs} ) { @files{ @{ $sapp->{htdocs} } } = (); foreach $file ( @{ $sapp->getHtdocsFiles() } ) { if ( $file =~ /\.htaccess$/ ) { my $_file = $file; $_file =~ s/\.htaccess$/.htpasswd/; if ( !exists $files{$_file} && -e "$htdocs_dir/$_file" ) { push @{ $sapp->{htdocs} }, $_file; } } } } if ( 'domain' eq $parentType ) { $proc = $self->getSubroutineRef("setDomainSappHttpContent"); } elsif ( 'subdomain' eq $parentType ) { $proc = $self->getSubroutineRef("setSubDomainSappHttpContent"); } $self->{packer}->$proc( $parent, $sapp_id, $htdocs_dir, $sapp->{htdocs}, $webspaceId ); if ($self->{include_app_distrib}) { my $distrib_path = AgentConfig::get("PRODUCT_ROOT_D") . "/var/apspkgarc"; my $file_name = $self->getApsArchiveFileName($distrib_path, $sapp->getName()."-".$sapp->getVersion()."-".$sapp->getRelease()); # what about absent release??? $self->{packer}->setServerSettings() unless defined $self->{packer}->{serverNode}; $self->{packer}->addServerAppPackage($sapp->getName(), $sapp->getVersion(), $sapp->getRelease(), $distrib_path, $file_name); } } sub makeDomainLogrotationNode { my ( $self, $domainId ) = @_; if ( PleskVersion::atLeast( 5, 0, 0 ) ) { my $sql = "SELECT val FROM dom_param WHERE param = 'logrotation_id' " . "AND dom_id=$domainId"; my $ptrRow; if ( $self->{dbh}->execute_rownum($sql) ) { $ptrRow = $self->{dbh}->fetchrow(); } $self->{dbh}->finish(); if ( defined $ptrRow ) { my $logrotation_id = $ptrRow->[0]; my %logrot = $self->makeLogrotationNode($logrotation_id); $self->{packer}->setDomainLogrotation( $domainId, \%logrot ); } } } sub makeLogrotationNode { my ( $self, $logrotation_id ) = @_; my $sql = "SELECT * FROM log_rotation WHERE id=$logrotation_id"; my %logRotation = (); if ( $self->{dbh}->execute_rownum($sql) and my $hashPtr = $self->{dbh}->fetchhash() ) { %logRotation = %{$hashPtr}; } $self->{dbh}->finish(); return %logRotation; } #----------------------------------------------------------------- # $ptrSubDomain - pointer to hash with subdomain's info (row of table 'subdomains') # $domainName - name of domain # $ptrSiteApplications - pointer to list of domain's site applications #----------------------------------------------------------------- sub dumpSubDomain( $ $ $ ) { my ( $self, $domainId, $ptrSubDomain, $domainName, $ptrSiteApplications ) = @_; unless ( ref($ptrSubDomain) =~ /HASH/ ) { Packer::printToError("Error: dumpSubDomain: bad argumets"); return undef; } my $subDomainName; my $subAsciiDomainName; if ( PleskVersion::atLeast( 7, 1, 0 ) ) { $subDomainName = $ptrSubDomain->{'displayName'}; $subAsciiDomainName = $ptrSubDomain->{'name'}; } else { $subDomainName = $ptrSubDomain->{'name'}; } # Subdomains may be SSL-enabled since 8.0 my $https = ''; my $shared_content = ''; if ( PleskVersion::atLeast( 8, 0, 0 ) ) { if ( 'true' eq $ptrSubDomain->{'ssl'} ) { $https = 'true'; } $shared_content = $ptrSubDomain->{'same_ssl'}; } # sysuser my %sysuser; if ( $ptrSubDomain->{'sys_user_type'} =~ /native/ ) { my %additionalSysuser; $additionalSysuser{'sys_user_id'} = $ptrSubDomain->{'sys_user_id'}; $self->makeSubFtpUserNode(\%additionalSysuser, $domainId, $domainName); } # scripting my %scripting; while ( my ( $xmlName, $fieldName ) = each(%subDomainScripting) ) { next if $fieldName =~ /asp_dot_net/; if ( $ptrSubDomain->{$fieldName} eq 'true' or $ptrSubDomain->{$fieldName} eq 'false' ) { $scripting{$xmlName} = $ptrSubDomain->{$fieldName}; } elsif( $xmlName eq 'php_handler_type' ){ $scripting{$xmlName} = $ptrSubDomain->{$fieldName} if $ptrSubDomain->{$fieldName}; $scripting{$xmlName} = 'isapi' if $scripting{$xmlName} eq 'module'; } } delete $scripting{'php_handler_type'} if exists $scripting{'php_handler_type'} and ( not exists $scripting{'php'} or $scripting{'php'} eq 'false'); $self->{packer}->addSubDomain( $domainId, $ptrSubDomain, $subDomainName, $subAsciiDomainName, $https, $shared_content, \%sysuser, \%scripting ); #----------------------------------------------------------------- # Site applications content should not be included into dump # together with other subdomain's content. #----------------------------------------------------------------- my @SiteApplications = @{$ptrSiteApplications}; my @exclude_httpdocs_files; my @exclude_httpsdocs_files; my @exclude_cgi_bin_files; foreach my $sapp (@SiteApplications) { next if !$sapp->isSubdomainSiteapp( $ptrSubDomain->{'id'} ); if ( $sapp->isSsl() ) { push @exclude_httpsdocs_files, $sapp->getHtdocsFiles(); } else { push @exclude_httpdocs_files, $sapp->getHtdocsFiles(); } push @exclude_cgi_bin_files, $sapp->getCgibinFiles(); } # content my $webspaceId = $self->getWebspaceId($domainId); #used for Site content-related subs my $subDomainRoot = $self->getWebspaceRoot($domainName) . "/subdomains/$subDomainName"; my $subDomainWwwRoot = $self->getSubDomainWwwRoot($ptrSubDomain->{'id'}, 'absolute'); if ( -d $subDomainWwwRoot and not $self->{configuration_dump} ) { $self->{packer}->setSubDomainHttpdocsContent( $ptrSubDomain->{'id'}, $subDomainName, $domainName, $subDomainWwwRoot, \@exclude_httpdocs_files, $webspaceId ); } if ( -d $subDomainRoot."/httpsdocs" and not $self->{configuration_dump} ) { $self->{packer}->setSubDomainHttpsdocsContent( $ptrSubDomain->{'id'}, $subDomainName, $domainName, "$subDomainRoot/httpsdocs", \@exclude_httpsdocs_files ); } my $subDomainCgiRoot = $self->getSubDomainCgiRoot($ptrSubDomain->{'id'}, 'absolute'); if ( -d $subDomainCgiRoot and not $self->{configuration_dump} ) { $self->{packer}->setSubDomainCgibinContent( $ptrSubDomain->{'id'}, $subDomainName, $domainName, $subDomainCgiRoot, \@exclude_cgi_bin_files, $webspaceId ); } if ( -d $subDomainRoot and not $self->{configuration_dump} ) { $self->{packer}->setSubDomainConfContent( $ptrSubDomain->{'id'}, $subDomainName, $domainName, "$subDomainRoot/conf" ); if (PleskVersion::isSmb()) { $self->{packer}->setSMBSubDomainSappScriptsContent($ptrSubDomain->{'id'}, "$subDomainRoot/vault_scripts", "$subDomainRoot/vault_https_scripts"); } } # Dump of installed site applications foreach my $sapp (@SiteApplications) { if ( !$sapp->isSubdomainSiteapp( $ptrSubDomain->{'id'} ) ) { next; } $self->dumpSiteApplication( $sapp, $subDomainRoot, $subDomainWwwRoot, $subDomainCgiRoot, $ptrSubDomain->{'id'}, 'subdomain', $webspaceId); } } # # makeWebUserNode # # argumenets: # $ptrWebUser - pointer to hash with web user's info (row of table 'web_users') # $domainName - name of domain # # return: # $root = XML node # sub makeWebUserNode { my ( $self, $ptrWebUser, $domainId, $domainName ) = @_; unless ( ref($ptrWebUser) =~ /HASH/ ) { &Packer::printToError("Error: makeWebUserNode: bad argumets"); return undef; } my ( $home, $fileName, $userName, $item, $xmlName, $fieldName ); my %sysuser; if ( PleskVersion::atLeast( 5, 0, 0 ) ) { %sysuser = $self->makePleskSysUserNode( $ptrWebUser->{'sys_user_id'} ); $userName = $sysuser{'login'}; } else { $userName = $ptrWebUser->{'username'}; my @pwnam = getpwnam($userName); my $password = $pwnam[1]; %sysuser = $self->makeSyntheticSysUserNode( $userName, $password, 'encrypted' ); } my $webUserHome = $self->getDomainRoot($domainName) . "/web_users/$userName"; my $privateData = $self->getDomainRoot($domainName) . "/private/$userName"; $self->{packer}->addDomainWebUser( $domainId, $domainName, \%sysuser, $ptrWebUser, $webUserHome, $privateData ); } # # makeSubFtpUserNode - make node for additionals ftp accounts # sub makeSubFtpUserNode { my ( $self, $ptrFtpUser, $domainId, $domainName ) = @_; my %sysuser = $self->makePleskSysUserNode($ptrFtpUser->{'sys_user_id'}); $sysuser{'relative_path'} = $self->getDefaultWebspaceRoot($domainName); $self->{packer}->addDomainSubFtpUser($domainId, $domainName, \%sysuser); } # # makeProtDirNode - make protected directory node # # arguments: # $pdirId - ID # $pdirPath - path of protected directory # $pdirTitle - header text # $pdirNonSSL - whether is directory in http # $pdirSSL - or in https # # return: # $root - XML node # sub makeProtDirNode { my ( $self, $domainId, $pdirId, $pdirPath, $pdirTitle, $pdirNonSSL, $pdirSSL, $pdirCGI ) = @_; my ( $sql, $userNode, $item, $ptrRow ); # workaround of CLI inabliity to create '' directory. if ( $pdirPath eq '' ) { $pdirPath = '/'; } if ( PleskVersion::atLeast( 7, 1, 0 ) ) { $sql = "SELECT p.login, a.password, a.type FROM pd_users p " . " LEFT JOIN accounts a ON p.account_id = a.id " . " WHERE p.pd_id=$pdirId ORDER BY p.id"; } else { $sql = "SELECT p.login, p.passwd, 'plain' FROM pd_users p " . " WHERE p.pd_id=$pdirId ORDER BY p.id"; } my @users; if ( $self->{dbh}->execute_rownum($sql) ) { while ( $ptrRow = $self->{dbh}->fetchrow() ) { push @users, { 'login' => $ptrRow->[0], 'passwd' => $ptrRow->[1], 'passwdType' => $ptrRow->[2] }; } } $self->{dbh}->finish(); $self->{packer}->addDomainProtectedDir( $domainId, $pdirPath, $pdirTitle, $pdirNonSSL, $pdirSSL, $pdirCGI, \@users ); } sub addAnonFtp { my ( $self, $domainId, $domainName, $optPtr ) = @_; my ( $anonRoot, $ptrHash, $count, $domainRoot, $sql ); $count = 0; $sql = "SELECT * FROM anon_ftp WHERE dom_id=$domainId"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( $ptrHash = $self->{dbh}->fetchhash() ) { $domainRoot = $self->getDomainRoot($domainName); my ( $pub_path, $incoming_path ); if ( -d $domainRoot ) { $pub_path = "$domainRoot/anon_ftp/pub"; $incoming_path = "$domainRoot/anon_ftp/incoming"; } $self->{packer}->setDomainAnonFtp( $domainId, $domainName, $ptrHash, $pub_path, $incoming_path, $optPtr ); $count++; } } $self->{dbh}->finish(); return $count; } sub addSb5DomainContent { my ( $self, $domainId, $domainName, $uuid ) = @_; unless ( defined $uuid) { Logging::info( "addSb5DomainContent: domain $domainName site_builder_site_id is not found. skip"); return; } $self->{packer}->setSb5DomainContent( $domainId, $domainName, $uuid); } sub getSysUserInfo { my ( $self, $sysUserId ) = @_; my $sql = "SELECT * FROM sys_users WHERE id=$sysUserId"; my $hashPtr; unless ( ( $self->{dbh}->execute_rownum($sql) ) && ( $hashPtr = $self->{dbh}->fetchhash() ) ) { $self->{dbh}->finish(); my $msg = "Broken referencial integrity: Sys user id $sysUserId is not found in sys_users"; print STDERR "$msg\n"; Packer::printToError( $msg ); return; } my %sysuser = %{ $hashPtr }; $self->{dbh}->finish(); return %sysuser; } sub makePleskSysUserNode { my ( $self, $sysUserId ) = @_; my %sysuser = $self->getSysUserInfo($sysUserId); Logging::trace("Making system user node: $sysuser{'login'}"); # # attributes # my $quota; if ( $sysuser{'quota'} ) { if ( PleskVersion::atLeast( 7, 0, 0 ) ) { $quota = $sysuser{'quota'}; } else { if ( $sysuser{'quota'} ne "-1" ) { $quota = $sysuser{'quota'} * 1024 * 1024; } } $sysuser{'quota'} = $quota if $quota; } # # end attributes # # # password node # if ( PleskVersion::atLeast( 6, 0, 0 ) ) { if ( $sysuser{'account_id'} != 0 ) { ( $sysuser{'passwd'}, $sysuser{'passwdType'} ) = $self->makeAccountPasswordNode( $sysuser{'account_id'} ); } } else { $sysuser{'passwd'} = $sysuser{'passwd'}; $sysuser{'passwdType'} = 'plain'; } # # end password node # # # crontab node # if( ! $self->{configuration_dump} ) { my $crontabmng = AgentConfig::get("PRODUCT_ROOT_D") . "/admin/sbin/crontabmng"; if ( -x $crontabmng ) { open( CRONTAB, "$crontabmng get $sysuser{'login'} |" ); my $crontab = ""; while () { last if $_ eq "0\n"; $crontab .= $_; } close(CRONTAB); if ( $crontab ne "\n" ) { $sysuser{'cron'} = $crontab; } } } # # end crontab node # return %sysuser; } sub makeSyntheticSysUserNode { my ( $self, $name, $password, $passtype ) = @_; my %sysuser; $sysuser{'login'} = $name; $sysuser{'passwd'} = $password; $sysuser{'passwdType'} = $passtype; return %sysuser; } sub makeFhostingNode { my ( $self, $ptrDomain ) = @_; return if ( $self->{only_mail_dump} ); unless ( ref($ptrDomain) =~ /HASH/ ) { &Packer::printToError("Error: makeFhostingNode: bag arguments"); return undef; } my ( $sql, $domainId, $forward, $rowPtr ); $domainId = $ptrDomain->{'id'}; $sql = "SELECT redirect FROM forwarding WHERE dom_id=$domainId"; unless ( ( $self->{dbh}->execute_rownum($sql) ) && ( $rowPtr = $self->{dbh}->fetchrow() ) ) { $self->{dbh}->finish(); my $msg = "Broken referencial integrity: forward for domain " . $ptrDomain->{'name'} . " is not found in forwarding"; print STDERR "$msg\n"; Packer::printToError( $msg ); return; } ($forward) = @{ $rowPtr }; $self->{packer}->setDomainFhosting( $domainId, $forward); $self->{dbh}->finish(); } sub makeShostingNode { my ( $self, $ptrDomain ) = @_; return if ( $self->{only_mail_dump} ); unless ( ref($ptrDomain) =~ /HASH/ ) { &Packer::printToError("Error: makeShostingNode: bag arguments"); return undef; } my ( $sql, $domainId, $forward, $rowPtr ); $domainId = $ptrDomain->{'id'}; $sql = "SELECT redirect FROM forwarding WHERE dom_id=$domainId"; unless ( ( $self->{dbh}->execute_rownum($sql) ) && ( $rowPtr = $self->{dbh}->fetchrow() ) ) { $self->{dbh}->finish(); my $msg = "Broken referencial integrity: forward for domain " . $ptrDomain->{'name'} . " is not found in forwarding"; print STDERR "$msg\n"; Packer::printToError( $msg ); return; } ($forward) = @{ $rowPtr }; $self->{packer}->setDomainShosting( $domainId, $forward ); $self->{dbh}->finish(); } # sub getClientIps { # my ($clientId) = @_; # if (PleskVersion::atLeast(6, 0, 0)) { # } elsif (PleskVersion::atLeast(5, 0, 0)) { # my $sql = "SELECT d.name, d.id, h.ip_address, a.status, d.cl_id FROM domains d " # . "LEFT JOIN hosting h ON h.dom_id = d.id " # . "LEFT JOIN anon_ftp a ON a.dom_id = d.id" # . "WHERE cl_id = $clientId"; # } else { # } # } # # Returns password node for given account ID # sub _makePasswordData{ my ($password, $type) = @_; if (!defined $password) { Packer::printToError( "'undef' password passed to _makePasswordData. Change to empty!" ); $password = ''; } if (!$password) { $type = 'plain'; } else { if ($type ne 'plain') { $type = 'encrypted'; } } return ($password, $type); } my $tableAccounts = undef; sub makeAccountPasswordNode { my ( $self, $accountId ) = @_; my ( $passwd, $type ); my %values; if( not defined $tableAccounts ){ if ( $self->{dbh}->execute( "SELECT id, password, type FROM accounts" ) ) { while( my $ptrRow = $self->{dbh}->fetchrow() ){ $values{$ptrRow->[0]} = (); push @{$values{$ptrRow->[0]}}, $ptrRow->[1]; push @{$values{$ptrRow->[0]}}, $ptrRow->[2]; } } $self->{dbh}->finish(); $tableAccounts = \%values; } if ( exists $tableAccounts->{$accountId} ) { ( $passwd, $type ) = @{$tableAccounts->{$accountId}}; ( $passwd, $type ) = _makePasswordData( $passwd, $self->{packer}->normalizePasswordType($type) ); } else { # generates a stub node ( $passwd, $type ) = _makePasswordData(); } $self->{dbh}->finish(); return ( $passwd, $type ); } my @_planItemNames; sub getPlanItemNames { my ( $self ) = @_; if ( @_planItemNames ) { return \@_planItemNames; } my $planItemsPtr = $self->getPlanItems(); foreach my $planItemPtr ( @{$planItemsPtr} ) { push @_planItemNames, $planItemPtr->{'name'}; } return \@_planItemNames; } sub getSubscriptionProperties { my ( $self, $type, $id ) = @_; my @planItemNames = @{$self->getPlanItemNames()}; my $subscriptionProperties = $self->getSubscriptionPropertiesHash($id, $type); foreach my $key (keys %{$subscriptionProperties}) { if ( grep $_ eq $key, @planItemNames) { my $templatePlanItemNode = $self->{packer}->makeTemplatePlanItem( $key, $subscriptionProperties->{$key} ); $self->{packer}->addToPreferences('domain', $id, $templatePlanItemNode) if defined $templatePlanItemNode; } } } sub getSubscriptionPropertiesHash { my ( $self, $id, $type ) = @_; my %subscriptionProperties; my $sql = "SELECT name, value FROM SubscriptionProperties INNER JOIN Subscriptions ON id=subscription_id WHERE object_id='$id' AND object_type='$type'"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( my $ptrHash = $self->{dbh}->fetchhash() ) { $subscriptionProperties{$ptrHash->{'name'}} = $ptrHash->{'value'}; } } $self->{dbh}->finish(); return \%subscriptionProperties; } sub getSubscription { my ( $self, $type, $id) = @_; my $subscriptionNode = $self->makeSubscriptionNode($type, $id); $self->{packer}->addToPreferences($type, $id, $subscriptionNode) if defined $subscriptionNode; } sub makeSubscriptionNode { my ( $self, $type, $id ) = @_; my $rowPtr; my $sql = "SELECT id, locked FROM Subscriptions WHERE object_id = '$id' AND object_type = '$type'"; if (PleskVersion::atLeast( 10, 1, 0) and not PleskVersion::isSmb()) { $sql .= " AND custom = 'false' "; } unless ( ( $self->{dbh}->execute_rownum($sql) ) && ( $rowPtr = $self->{dbh}->fetchrow() ) ){ $self->{dbh}->finish(); return; } my $subscription_id = $rowPtr->[0]; my $locked = $rowPtr->[1]; $self->{dbh}->finish(); my %planQuantity; my $subscriptionNode = XmlNode->new( 'subscription', 'attributes' => { 'locked' => $locked } ); $sql = "SELECT plan_id, quantity FROM PlansSubscriptions WHERE subscription_id = '$subscription_id'"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( my $row = $self->{dbh}->fetchrow() ) { $planQuantity{$row->[0]} = $row->[1]; } } $self->{dbh}->finish(); while ( my ($planId, $quantity) = each(%planQuantity) ) { $sql = "SELECT uuid, type FROM Templates WHERE id = '$planId'"; unless ( $self->{dbh}->execute_rownum($sql) ) { Logging::warning( "Error during getting uuid from plan '$planId'"); $self->{dbh}->finish(); next; } if ( my $row = $self->{dbh}->fetchrow() ) { my $planGuid = $row->[0]; my $type = $row->[1]; $self->{dbh}->finish(); my $planNode = XmlNode->new( 'plan', 'attributes' => { 'quantity' => $quantity, 'plan-guid' => $planGuid } ); if ($type eq 'domain_addon') { $planNode->setAttribute('is-addon', 'true'); } $subscriptionNode->addChild($planNode); } $self->{dbh}->finish(); } return $subscriptionNode; } sub makeSpamassassinNode { if ( PleskVersion::atLeast( 10, 0, 0 ) and not PleskVersion::isSmb() ) { makeSpamassassinNode100(@_); } elsif ( PleskVersion::atLeast( 8, 1, 0 ) ) { makeSpamassassinNode81(@_); } elsif ( PleskVersion::atLeast( 7, 0, 0 ) ) { my ( $self, $mailId, $mailNm, $domainAsciiname, $status, $dir ) = @_; $self->makeSpamassassinNode70( $mailId, $mailNm, $domainAsciiname, $dir ); } } sub makeSpamassassinNode100 { my ( $self, $mailId, $mailNm, $domainAsciiname, $status, $dir ) = @_; my $mailname = $mailNm . '@' . $domainAsciiname; my $rowPtr; my $sql = "SELECT id, preferences FROM spamfilter WHERE username = '$mailname'"; unless ( ( $self->{dbh}->execute_rownum($sql) ) && ( $rowPtr = $self->{dbh}->fetchrow() ) ) { $self->{dbh}->finish(); Logging::warning( "Error during getting information about spam filter for $mailname"); return; } my $filter_id = $rowPtr->[0]; my $server = 0; my $rownum; do { $self->{dbh}->finish(); if ($server) { $sql = "SELECT id FROM spamfilter WHERE username = '*@*'"; if ( ( $self->{dbh}->execute_rownum($sql) ) && ( my $row = $self->{dbh}->fetchrow() ) ) { $filter_id = $row->[0]; } $self->{dbh}->finish(); } $sql = "SELECT preference, value FROM spamfilter_preferences WHERE spamfilter_id = '$filter_id' ORDER BY length(preference), preference"; $rownum = $self->{dbh}->execute_rownum($sql); } while ( !$rownum && !$server++ ); my ( @blacckList, @whiteList, @unblackList, @unwhiteList ); my ( $action, $requiredScore, $subj_text ); while ( my $row = $self->{dbh}->fetchrow() ) { push @blacckList, $row->[1] if $row->[0] eq "blacklist_from"; push @whiteList, $row->[1] if $row->[0] eq "whitelist_from"; push @unblackList, $row->[1] if $row->[0] eq "unblacklist_from"; push @unwhiteList, $row->[1] if $row->[0] eq "unwhitelist_from"; $requiredScore = $row->[1] if ( $row->[0] eq "required_score" ); $action = $row->[1] if ( $row->[0] eq "action" ); if ( $row->[0] eq "rewrite_header" ) { $row->[1] =~ s/^subject //; $subj_text = $row->[1]; } } $self->{dbh}->finish(); if( $action ne 'delete' && $action ne 'move' ) { $action = 'mark'; } my %spamServerSettings = undef; if ($mailname eq "*@*") { $sql = "SELECT * FROM misc WHERE param RLIKE '^spamfilter_'"; if ( $self->{dbh}->execute_rownum($sql) ) { while (my $row = $self->{dbh}->fetchrow() ) { $spamServerSettings{$row->[0]} = $row->[1]; } } $status = $spamServerSettings{'spamfilter_enabled'}; $self->{dbh}->finish(); } $self->{packer}->setMailSpamSettings( $mailId, $mailNm, $domainAsciiname, ( $status eq 'true' ? 'on' : 'off' ), undef, $action, $requiredScore, undef, $subj_text, \@blacckList, \@whiteList, \@unblackList, \@unwhiteList, $dir, (defined(%spamServerSettings) ? \%spamServerSettings : undef) ); } sub makeSpamassassinNode81 { my ( $self, $mailId, $mailNm, $domainAsciiname, $status, $dir ) = @_; my $mailname = $mailNm . '@' . $domainAsciiname; my $rowPtr; my $sql = "SELECT id, preferences, reject_spam FROM spamfilter WHERE username = '$mailname'"; unless ( ( $self->{dbh}->execute_rownum($sql) ) && ( $rowPtr = $self->{dbh}->fetchrow() ) ) { $self->{dbh}->finish(); Logging::warning( "Error during getting information about spam filter for $mailname"); return; } my $filter_id = $rowPtr->[0]; my $reject_spam = $rowPtr->[2]; my $server = 0; my $rownum; do { $self->{dbh}->finish(); if ($server) { $sql = "SELECT id FROM spamfilter WHERE username = '*@*'"; if ( ( $self->{dbh}->execute_rownum($sql) ) && ( my $row = $self->{dbh}->fetchrow() ) ) { $filter_id = $row->[0]; } $self->{dbh}->finish(); } $sql = "SELECT preference, value FROM spamfilter_preferences WHERE spamfilter_id = '$filter_id' ORDER BY length(preference), preference"; $rownum = $self->{dbh}->execute_rownum($sql); } while ( !$rownum && !$server++ ); my ( @blacckList, @whiteList, @unblackList, @unwhiteList ); my ( $requiredScore, $subj_text ); while ( my $row = $self->{dbh}->fetchrow() ) { push @blacckList, $row->[1] if $row->[0] eq "blacklist_from"; push @whiteList, $row->[1] if $row->[0] eq "whitelist_from"; push @unblackList, $row->[1] if $row->[0] eq "unblacklist_from"; push @unwhiteList, $row->[1] if $row->[0] eq "unwhitelist_from"; $requiredScore = $row->[1] if ( $row->[0] eq "required_score" ); if ( $row->[0] eq "rewrite_header" ) { $row->[1] =~ s/^subject //; $subj_text = $row->[1]; } } $self->{dbh}->finish(); my %spamServerSettings = undef; if ($mailname eq "*@*") { $sql = "SELECT * FROM misc WHERE param RLIKE '^spamfilter_'"; if ( $self->{dbh}->execute_rownum($sql) ) { while (my $row = $self->{dbh}->fetchrow() ) { $spamServerSettings{$row->[0]} = $row->[1]; } } $status = $spamServerSettings{'spamfilter_enabled'}; $self->{dbh}->finish(); } $self->{packer}->setMailSpamSettings( $mailId, $mailNm, $domainAsciiname, ( $status eq 'true' ? 'on' : 'off' ), undef, ( $reject_spam eq 'true' ? 'delete' : 'mark' ), $requiredScore, undef, $subj_text, \@blacckList, \@whiteList, \@unblackList, \@unwhiteList, $dir, (defined(%spamServerSettings) ? \%spamServerSettings : undef) ); } sub makeSpamassassinNode70 { my ( $self, $mailId,, $mailNm, $domainAsciiname, $dir ) = @_; my $mailName = $mailNm . '@' . $domainAsciiname; my $rowPtr; my $sql = "SELECT count(*) FROM sa_conf WHERE mailname='$mailName'"; unless ( ( $self->{dbh}->execute_rownum($sql) ) && ( $rowPtr = $self->{dbh}->fetchrow() ) ) { $self->{dbh}->finish(); my $msg = "Broken referencial integrity: mailname $mailName is not found in sa_conf"; print STDERR "$msg\n"; Packer::printToError( $msg ); return; } my @row = @{ $rowPtr }; $self->{dbh}->finish(); if ( $row[0] == 0 ) { return; } my $status = undef; my $action = undef; my $server_conf = undef; my $requiredScore = undef; my $subj_text = undef; my $hashPtr; $sql = "SELECT * FROM sa_conf WHERE mailname='$mailName'"; unless ( ( $self->{dbh}->execute_rownum($sql) ) && ( $hashPtr = $self->{dbh}->fetchhash() ) ) { $self->{dbh}->finish(); my $msg = "Broken referencial integrity: mailname $mailName is not found in sa_conf"; print STDERR "$msg\n"; Packer::printToError( $msg ); return; } my %spam = %{ $hashPtr }; $self->{dbh}->finish(); my $item; if ( $spam{'flt_enabled'} eq 'both' ) { $status = 'on'; $server_conf = 'true'; } elsif ( $spam{'flt_enabled'} eq 'user' ) { $status = 'on'; $server_conf = 'false'; } else { #skip creation return; } $requiredScore = $spam{'hits_required'}; if ( $spam{'spam_action'} eq 'save' ) { $action = 'mark'; } else { $action = 'delete'; } my ( $modify_subj ); if ( $spam{'rw_subject_tag'} ) { $modify_subj = 'true'; $subj_text = $spam{'rw_subject_tag'}; } else { $modify_subj = 'false'; } my @blacckList = $self->addSpamassassinPatterns( $spam{'mailname'}, 'black' ); my @whiteList = $self->addSpamassassinPatterns( $item, $spam{'mailname'}, 'white' ); my @empty; $self->{packer}->setMailSpamSettings( $mailId, $mailNm, $domainAsciiname, $status, $server_conf, $action, $requiredScore, $modify_subj, $subj_text, \@blacckList, \@whiteList, \@empty, \@empty, $dir, undef ); } sub addSpamassassinPatterns { my ( $self, $mailname, $color ) = @_; my @ret; my $rowPtr; my $sql = "SELECT pattern FROM sa_list WHERE mailname='$mailname' AND color = '$color'"; if ($self->{dbh}->execute($sql)) { while ($rowPtr = $self->{dbh}->fetchrow()) { push @ret, $rowPtr->[0]; } $self->{dbh}->finish(); return @ret; } else { $self->{dbh}->finish(); my $msg = "Broken referencial integrity: ${color}list patterns for $mailname is not found in sa_list"; print STDERR "$msg\n"; Packer::printToError( $msg ); return @ret; } } sub makeDrwebNode { my ( $self, $mailname ) = @_; my $drwebFile = "/etc/drweb/users.conf"; unless ( open( DRWEBFILE, "<$drwebFile" ) ) { Packer::printToLog("Error: unable to open $drwebFile"); return; } while () { chomp; next if /^#/; #skip comments next if /^\[/; next if /^\s*$/; my @parts = split /\s+/, $_, 4; if ( $parts[3] =~ /$mailname/ ) { if ( $parts[1] =~ /to/ ) { return 'in'; } elsif ( $parts[1] =~ /from/ ) { return 'out'; } else { return 'inout'; } last; } } close(DRWEBFILE); return 'none'; } sub makeWebAppNode { my ( $self, $domainId, $webAppName, $webAppStatus, $dom_name ) = @_; # webapp is useless without cid $webAppStatus ||= 0; my $warDir = AgentConfig::get("CATALINA_HOME") . "/psa-wars/$dom_name"; $self->{packer}->addDomainTomcatWebApp( $domainId, $dom_name, $webAppName, $webAppStatus, $warDir ); } sub getCustomButtonById71( $ ) { my ( $self, $id, $parent, $parentType, $sappId ) = @_; my $proc; if( $sappId ){ if ( 'domain' eq $parentType ) { $proc = $self->getSubroutineRef("addDomainSappCustomButton"); } elsif ( 'subdomain' eq $parentType ) { $proc = $self->getSubroutineRef("addSubDomainSappCustomButton"); } else { Packer::printToError( "Error: getCustomButtonById71: Unexpected type of siteapp parent '$parentType'"); return; } } else{ if ( 'server' eq $parentType ) { $proc = $self->getSubroutineRef("addServerCustomButton"); } elsif ( 'client' eq $parentType || 'reseller' eq $parentType ) { $proc = $self->getSubroutineRef("addClientCustomButton"); } elsif ( 'domain-admin' eq $parentType ) { $proc = $self->getSubroutineRef("addDomainCustomButton"); } elsif ( 'mailuser' eq $parentType ) { $proc = $self->getSubroutineRef("addMailCustomButton"); } elsif ( 'sapp' eq $parentType ) { $proc = $self->getSubroutineRef("addSappCustomButton"); } else { Packer::printToError("Error: getCustomButtonById71: Unexpected type of parent '$parentType'"); return; } } my $options; # several times there was empty button place in database, which is incorrect my $sql = "SELECT * FROM custom_buttons WHERE id=$id AND place!=''"; unless ( ( $self->{dbh}->execute_rownum($sql) ) && ( $options = $self->{dbh}->fetchhash() ) ) { $self->{dbh}->finish(); return; } $self->{dbh}->finish(); my $customButtonsDir = AgentConfig::get("PRODUCT_ROOT_D") . '/admin/htdocs/images/custom_buttons'; my $icon = $options->{'file'}; if( $sappId ){ $self->{packer}->$proc( $parent, $sappId, $id, $options, $customButtonsDir, $icon ); } else{ if ( 'server' eq $parentType ) { $self->{packer}->$proc( $id, $options, $customButtonsDir, $icon ); } else { $self->{packer}->$proc( $parent, $id, $options, $customButtonsDir, $icon ); } } } sub getCustomButtonIdsByOwner71 { my ( $self, $owner_type, $owner_id ) = @_; my $level = $custom_button_owner_types{$owner_type}; my $sql = "SELECT id FROM custom_buttons WHERE level='$level' AND level_id='$owner_id'"; if ( !$self->{dbh}->execute_rownum($sql) ) { $self->{dbh}->finish(); return; } my @ids; while ( my $ptrRow = $self->{dbh}->fetchrow() ) { my $id = $ptrRow->[0]; if ( grep /^$id$/, @{ $self->{skip_custom_buttons} } ) { next; } push @ids, $id; } $self->{dbh}->finish(); return @ids; } sub getCustomButtonsByOwner71 { my ( $self, $owner_type, $owner_id ) = @_; my @ids = $self->getCustomButtonIdsByOwner71($owner_type, $owner_id); return unless @ids; return map { $self->getCustomButtonById71( $_, $owner_id, $owner_type ) } @ids; } sub getCustomButtonsByOwner65 { my ( $self, $owner_type, $owner_id ) = @_; return if ( $owner_type ne "client" ); my $sql = "SELECT text, url, conhelp, options FROM custom_buttons WHERE " . "cl_id=$owner_id"; my @nodes; if ( $self->{dbh}->execute_rownum($sql) ) { my $ptrHash; while ( $ptrHash = $self->{dbh}->fetchhash() ) { my $node = XmlNode->new( 'custom-button', 'attributes' => { 'sort-priority' => '100', 'interface-place' => 'domain' } ); my %attributes = ( 'url' => 'url', 'text' => 'text', 'conhelp' => 'conhelp' ); while ( my ( $dbfield, $nodefield ) = each %attributes ) { $node->{'ATTRIBUTE'}->( $nodefield, $ptrHash->{$dbfield} ); } ## 128 == CUSTOM_BUTTON_PUBLIC parseCustomButtonOptions( $node, $ptrHash->{'options'} | 128 ); push @nodes, $node; } } $self->{dbh}->finish(); return @nodes; } sub getCustomButtonsByOwner { my $self = shift; return $self->getCustomButtonsByOwner71(@_) if ( PleskVersion::atLeast( 7, 1, 0 ) ); return $self->getCustomButtonsByOwner65(@_) if ( PleskVersion::atLeast( 6, 5, 0 ) ); return (); } sub makeDefaultIpNode { my ( $self, $parent ) = @_; my $sql = "SELECT ip_address FROM IP_Addresses ip, misc m WHERE ip.id = m.val AND m.param = 'def_ip_id'"; if ( ( $self->{dbh}->execute_rownum($sql) ) && ( my $ptrHash = $self->{dbh}->fetchhash() ) ) { $self->{packer}->setServerDefaultIp( $ptrHash->{'ip_address'} ); } $self->{dbh}->finish(); } sub makeAdminInfoNode { my ( $self, $ptrAdmin ) = @_; my ( $name, $value ); my $passwd = AgentConfig::get { 'password' }; my ( $skin, $max_btn_len, $send_announce, $external_id ); if( exists $ptrAdmin->{'admin_skin_id'} ){ my $sql = "SELECT `name` FROM `Skins` where `id`=" . $ptrAdmin->{'admin_skin_id'}; if ( $self->{dbh}->execute_rownum($sql) and my $ptrRow = $self->{dbh}->fetchrow() ){ $skin = $ptrRow->[0]; } $self->{dbh}->finish(); } if( exists $ptrAdmin->{'max_button_length'} ){ $max_btn_len = $ptrAdmin->{'max_button_length'}; delete $ptrAdmin->{'max_button_length'} } if( exists $ptrAdmin->{'send_announce'} ){ $send_announce = $ptrAdmin->{'send_announce'}; delete $ptrAdmin->{'send_announce'}; } if( exists $ptrAdmin->{'external_id'} ){ $external_id = $ptrAdmin->{'external_id'}; delete $ptrAdmin->{'external_id'}; } my %gappsInfo; if (PleskVersion::atLeast( 10, 0, 0) and not PleskVersion::isSmb()) { my $adminId = PleskStructure::getAdminId(); my $sql = "SELECT param, val FROM cl_param WHERE cl_id = " . $adminId; if ( $self->{dbh}->execute_rownum($sql) ) { while ( my $ptrHash = $self->{dbh}->fetchhash() ) { $gappsInfo{ $ptrHash->{'param'} } = $ptrHash->{'val'}; } } $self->{dbh}->finish(); } $self->{packer}->setServerAdminInfo( $ptrAdmin, $passwd, $skin, $max_btn_len, $send_announce, $external_id, \%gappsInfo ); } sub blockToNum { my ( $self, $mask ) = @_; my $longMask = unpack( "N", pack( "C4", split( /\./, $mask ) ) ); my $block; for ( $block = 0 ; $block < 32 ; $block = $block + 1 ) { my $tmp = 2**( 32 - $block - 1 ); last if !( $longMask & $tmp ); } return $block; } my @_planItems; sub getPlanItems { my ( $self) = @_; if ( @_planItems ) { return \@_planItems; } my $sql = "SELECT * from PlanItems"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( my $planItemPtr = $self->{dbh}->fetchhash() ) { push @_planItems, $planItemPtr; } } $self->{dbh}->finish(); return \@_planItems; } sub dumpPlanItems { my ( $self) = @_; my @planItems = @{$self->getPlanItems()}; if ( @planItems ) { my $customButtonsDir = AgentConfig::get("PRODUCT_ROOT_D") . '/admin/htdocs/images/custom_buttons'; foreach my $planItemPtr ( @planItems ) { my $sql = "SELECT name, value from PlanItemProperties WHERE plan_item_id = '" . $planItemPtr->{'id'} . "'"; if ( $self->{dbh}->execute_rownum($sql) ) { my %planItemProps; while ( my $planItemPropertyPtr = $self->{dbh}->fetchrow() ) { $planItemProps{$planItemPropertyPtr->[0]} = $planItemPropertyPtr->[1]; } $self->{packer}->addPlanItemToServer($planItemPtr, \%planItemProps, $customButtonsDir); } $self->{dbh}->finish(); } } } sub makeServerNode { my ( $self ) = @_; $self->{packer}->setServerSettings(); #Dump server skeleton my $skeletonPath = AgentConfig::get('HTTPD_VHOSTS_D') . "/.skel/0"; if ( !$self->{configuration_dump} ) { $self->{packer}->addServerSkeleton( $skeletonPath, "skel" ); my $customTemplatesPath = AgentConfig::get('PRODUCT_ROOT_D')."/admin/conf/templates/custom"; if (-d $customTemplatesPath) { $self->{packer}->addServerCustomApacheTemplates($customTemplatesPath); } if ( PleskVersion::atLeast( 10, 0, 0 ) and not PleskVersion::isSmb() ) { if (!$self->{only_mail_dump} ) { $self->{packer}->setSb5ServerContent(); $self->{packer}->addServerCustomHealthConfig(); } } if (PleskVersion::isSmb()) { my $sql = "SHOW TABLES LIKE 'smb_%'"; $self->{dbh}->execute_rownum($sql); my @smb_tables; while (my $row = $self->{dbh}->fetchrow() ) { push @smb_tables, $row->[0]; } $self->{dbh}->finish(); my %options; $options{name} = $self->{dbh}->getName(); $options{user} = $self->{dbh}->getUser(); $options{type} = $self->{dbh}->getType(); $options{password} = $self->{dbh}->getPassword(); $options{tables} = \@smb_tables; $options{replace_and_no_create_info} = 1; $self->{packer}->addSmbDbDump(\%options); if (AgentConfig::sbRoot()) { $self->{packer}->addSbDump(); } if (-d AgentConfig::get('HTTPD_VHOSTS_D')."/fs") { $self->{packer}->addFileSharingContent(AgentConfig::get('HTTPD_VHOSTS_D')."/fs"); } if (-d AgentConfig::get('HTTPD_VHOSTS_D')."/fs-passwd") { $self->{packer}->addFileSharingPasswd(AgentConfig::get('HTTPD_VHOSTS_D')."/fs-passwd"); } } } #Dump system and default ip my $sql = "SELECT ip_address, mask, iface, c.pvt_key pvtkey FROM IP_Addresses i INNER JOIN certificates c ON c.id = i.ssl_certificate_id"; my %ips; if ( $self->{dbh}->execute_rownum($sql) ) { while ( my $ptrHash = $self->{dbh}->fetchhash() ) { $ptrHash->{'type' } = PleskStructure::isExclusiveIp( $ptrHash->{'ip_address'} ) ? 'exclusive' : 'shared'; $self->{packer}->addServerIp($ptrHash); } } $self->{dbh}->finish(); $self->makeDefaultIpNode(); #Dump hostname $sql = "SELECT val FROM misc WHERE param = 'FullHostName'"; if ( ( $self->{dbh}->execute_rownum($sql) ) && ( my $ptrHash = $self->{dbh}->fetchhash() ) ) { $self->{packer}->setServerHostname("$ptrHash->{'val'}"); } $self->{dbh}->finish(); #Dump connection information to Billing $sql = "SELECT cp.param, cp.val FROM cl_param cp, clients c WHERE cp.cl_id = c.id AND c.login = 'admin'"; if ( $self->{dbh}->execute_rownum($sql) ) { my %connInfo; while ( my $ptrHash = $self->{dbh}->fetchhash() ) { $connInfo{ $ptrHash->{'param'} } = $ptrHash->{'val'}; } $self->{packer}->setPpbConnection(\%connInfo); } $self->{dbh}->finish(); #Dump admin info $sql = "SELECT param, val FROM misc WHERE param RLIKE '^admin' or param='send_announce' or param='max_button_length'" ; # do not use LIKE, bug #106566 my %admin; if ( $self->{dbh}->execute_rownum($sql) ) { while ( my $ptrHash = $self->{dbh}->fetchhash() ) { $admin{ $ptrHash->{'param'} } = $ptrHash->{'val'}; } } $self->{dbh}->finish(); my $adminId = PleskStructure::getAdminId(); $sql = "SELECT external_id FROM clients WHERE id = $adminId"; if ( $self->{dbh}->execute($sql) ) { if (my $ptrHash = $self->{dbh}->fetchhash() ) { $admin{'external_id'} = $ptrHash->{'external_id'}; } } $self->{dbh}->finish(); $self->makeAdminInfoNode( \%admin ); # Dump database servers if ( PleskVersion::atLeast( 8, 0, 0 ) ) { $sql = "SELECT param, val FROM misc WHERE param RLIKE '^default_server_'"; my %def; if ( $self->{dbh}->execute_rownum($sql) ) { while ( my $ptrHash = $self->{dbh}->fetchhash() ) { $def{ $ptrHash->{'param'} } = $ptrHash->{'val'}; } } $self->{dbh}->finish(); $sql = "SELECT id, host, port, type, admin_login, admin_password FROM DatabaseServers"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( my $ptrHash = $self->{dbh}->fetchhash() ) { my $param = 'default_server_' . $ptrHash->{'type'}; my $default = exists $def{$param} && $def{$param} == $ptrHash->{'id'}; my $passwd; if ( $ptrHash->{'type'} eq 'mysql' && $ptrHash->{'host'} eq 'localhost' ) { $passwd = AgentConfig::get('password'); } $self->{packer}->adddServerDb( $ptrHash, $passwd, $default ); } } $self->{dbh}->finish(); } my %params; if ( !$self->{shallow_dump} ) { if( !$self->{configuration_dump} ){ # Dump key info if ( PleskVersion::atLeast( 9, 0, 0 ) ) { my $phpini = AgentConfig::get('PRODUCT_ROOT_D') . "/admin/conf/php.ini"; my $swkeyrepo = '/etc/sw/keys'; if( -e $phpini ){ open PHPINI, $phpini; while () { chomp; next if /^#/; next if /^$/; if ( $_ =~ /swkey\.repository_dir\s*=\s*[\"\']?(.+)[\"\']\s*$/) { $swkeyrepo = $1; Packer::printToLog( "Found sw key repository: $swkeyrepo" ); last; } } close PHPINI; } if( -d "$swkeyrepo/keys" ){ my $keyDir = "$swkeyrepo/keys"; Packer::printToLog( "Load keys from '$keyDir'" ); opendir DIR, "$keyDir"; my @files = readdir( DIR ); closedir DIR; foreach my $key(@files){ if( $key ne '.' and $key ne '..' and -f "$keyDir/$key" ){ my $cmd = getLicenseCommand() . " --get-instance-id $keyDir/$key"; my $exec = `$cmd`; chomp($exec); $self->{packer}->addServerKey( $key, $key, $keyDir, 'false', $exec); } } } else{ Packer::printToError( "Keys directory '$swkeyrepo/keys' is not found. The keys are not included to backup." ); } } else{ $sql = "SELECT * FROM key_history WHERE filename IS NOT NULL"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( my $ptrHash = $self->{dbh}->fetchhash() ) { next if ( $ptrHash->{'filename'} =~ /\~$/ ); my @keyPath = split( /\//, $ptrHash->{'filename'} ); my ( $keyName, $keyDir, $additional ); if ( $keyPath[3] eq 'key.d' ) { $keyName = $keyPath[4]; $keyDir = "/etc/psa/key.d/"; $additional = "true"; } else { $keyName = $keyPath[3]; $keyDir = "/etc/psa/"; $additional = "false"; } if ( -e $keyDir . "/" . $keyName ) { $self->{packer}->addServerKey( $ptrHash->{'plesk_key_id'}, $keyName, $keyDir, $additional ); } } } $self->{dbh}->finish(); } } my $ptrRow; if ( $self->{dbh}->execute_rownum('SELECT param, val FROM misc') ) { while ( $ptrRow = $self->{dbh}->fetchrow() ) { $params{ $ptrRow->[0] } = $ptrRow->[1]; } } $self->{dbh}->finish(); my @unessential_params = ( 'spf_rules', 'spf-guess', 'spf-exp', 'rbl_server', 'spf_behavior', 'disable_pop_auth', 'disable_smtp_auth', 'spf_enabled', 'use_vocabulary', 'allow_short_pop3_names', 'dns_zone_status' ); foreach my $param (@unessential_params) { if ( !exists $params{$param} ) { $params{$param} = ''; } } # TODO: implement server settings backups for earlier Plesks if ( PleskVersion::atLeast( 8, 1, 0 ) ) { # Dump server settings $params{'rbl_server'} =~ s/;/,/g; # Dump mail settings my $mailmng = AgentConfig::get('PRODUCT_ROOT_D') . '/admin/sbin/mailmng'; my $letter_size = `$mailmng --get-max-letter-size`; chomp($letter_size); my @blackList; my %whiteList; # black list if ( $self->{dbh}->execute_rownum('SELECT domain FROM badmailfrom') ) { while ( $ptrRow = $self->{dbh}->fetchrow() ) { push @blackList, $ptrRow->[0]; } } $self->{dbh}->finish(); # white list if ( $self->{dbh}->execute_rownum('SELECT ip_address, ip_mask FROM smtp_poplocks') ) { while ( $ptrRow = $self->{dbh}->fetchrow() ) { $whiteList{$ptrRow->[0]} = $ptrRow->[1]; } } $self->{dbh}->finish(); $self->{packer}->setServerMail( $letter_size, \%params, \@blackList, \%whiteList ); # dump External Webmails my @externalWebmails; if (PleskVersion::atLeast(10, 1, 0) and not PleskVersion::isSmb()) { if ( $self->{dbh}->execute_rownum('SELECT name, url, enabled FROM externalWebmails ')) { while ( my $ptrHash = $self->{dbh}->fetchhash() ) { push @externalWebmails, $ptrHash; } } $self->{dbh}->finish(); if (scalar(@externalWebmails) > 0) { $self->{packer}->setExternalWebmails(\@externalWebmails); } } # dump dns my @records; if ( $self->{dbh}->execute_rownum('SELECT * FROM dns_recs_t') ) { while ( my $ptrHash = $self->{dbh}->fetchhash() ) { push @records, $ptrHash; } } $self->{dbh}->finish(); $self->{packer}->setServerDNS( \%params, \@records ); # dump certificates my @ids; my $cert_id = $params{'cert_rep_id'}; $sql = "SELECT c.id FROM certificates c, Repository r " . "WHERE c.id=r.component_id AND r.rep_id='$cert_id' ORDER BY c.id"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( $ptrRow = $self->{dbh}->fetchrow() ) { push @ids, $ptrRow->[0]; } } $self->{dbh}->finish(); my $defaultCert; foreach my $id (@ids) { if ( $params{'default_certificate_id'} == $id ) { $defaultCert = 1; } else { $defaultCert = 0; } $self->makeCertificateNode( $id, 0, 'server', $defaultCert ); } $self->{packer}->addPanelCertificate(); # dump custom buttons $self->getCustomButtonsByOwner( 'server', 0 ); $self->{packer}->setControlsVisibility( \%params ); if (PleskVersion::atLeast( 10, 0, 0 ) and not PleskVersion::isSmb()) { my $adminId = PleskStructure::getAdminId(); $self->dumpTemplates( $adminId, 'server', 'domain' ); $self->dumpTemplates( $adminId, 'server', 'domain_addon' ); $self->dumpTemplates( $adminId, 'server', 'reseller' ); if (PleskVersion::atLeast( 10, 1, 0 )) { $self->dumpPlanItems(); } } else { # dump domain templates $self->dumpTemplates9x( 0, 'server', $params{'dom_tmpl_list_id'}, 'domain' ); # dump reseller templates $self->dumpTemplates9x( 0, 'server', $params{'res_tmpl_list_id'}, 'reseller' ); } } if ( PleskVersion::atLeast( 8, 2, 0 ) ) { # dump SSO if (defined $params{'sso_server'}) { my $cert; if ( defined $params{'sso_certificate'} && -r $params{'sso_certificate'} ) { open( CERT, $params{'sso_certificate'} ); read( CERT, $cert, -s CERT ); close(CERT); } my $idpCert; if ( defined $params{'sso_idp_cert'} && -r $params{'sso_idp_cert'} ) { open( IDPCERT, $params{'sso_idp_cert'} ); read( IDPCERT, $idpCert, -s IDPCERT ); close(IDPCERT); } $self->{packer}->setServerSSO( \%params, $cert, $idpCert ); if ( PleskVersion::atLeast( 8, 3, 0 ) ) { # SSO branding my @branding; $sql = "SELECT * FROM SSOBranding"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( my $ptrRow = $self->{dbh}->fetchrow() ) { push @branding, $ptrRow; } } $self->{dbh}->finish(); $self->{packer}->setServerSSOBranding( \@branding ); } } # Dump misc parameters } } if ( PleskVersion::atLeast( 10, 0, 0 ) and not PleskVersion::isSmb() ) { $self->{packer}->setServerAppVault(); $self->{packer}->setServerPackagesPool(); $sql = "SELECT `name`, `version`, `release`, `cacheId`, `isUploaded`, `isVisible` FROM smb_apsPackages"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( my $ptrRow = $self->{dbh}->fetchrow() ) { my $distrib_path = AgentConfig::get("PRODUCT_ROOT_D") . "/var/apspackages/" . $ptrRow->[3] ; my $file_name = $ptrRow->[3] . ".app.zip"; $self->{packer}->addServerAppPackage( $ptrRow->[0], $ptrRow->[1], $ptrRow->[2], $distrib_path, $file_name, $ptrRow->[4], $ptrRow->[5] ); } } $self->{dbh}->finish(); } elsif ( PleskVersion::atLeast( 8, 3, 0 ) ) { if (!PleskVersion::isSmb()) { $self->{packer}->setServerAppVault(); my $distrib_path = AgentConfig::get("PRODUCT_ROOT_D") . "/var/apspkgarc"; $self->{packer}->setServerPackagesPool(); $sql = "SELECT `name`, `version`, `release` FROM SiteAppPackages"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( my $ptrRow = $self->{dbh}->fetchrow() ) { my $distrib_name = $ptrRow->[0] . "-" . $ptrRow->[1] . "-" . $ptrRow->[2]; # What if 1 and 2 does not exist, or they exist always? my $file_name = $self->getApsArchiveFileName($distrib_path, $distrib_name); $self->{packer}->addServerAppPackage( $ptrRow->[0], $ptrRow->[1], $ptrRow->[2], $distrib_path, $file_name ); } } $self->{dbh}->finish(); #Application Item $self->{packer}->setServerAppItemsPool(); my $aishared = "ai.shared"; if ( PleskVersion::atLeast( 9, 0, 0 ) ) { $aishared = "ai.disabled"; } $sql = "SELECT lt.license_type_hash AS license_type_id, sap.name AS sapp_name, sap.version AS sapp_version, sap.release AS sapp_release, $aishared AS shared, ai.disabled AS disabled " . "FROM APSApplicationItems AS ai INNER JOIN SiteAppPackages sap ON (sap.id = ai.pkg_id) " . "LEFT JOIN APSLicenseTypes AS lt ON (lt.id = ai.license_type_id)"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( my $ptrHash = $self->{dbh}->fetchhash() ) { $self->{packer}->addServerAppItem($ptrHash); } } $self->{dbh}->finish(); #Application License $self->{packer}->setServerAppLicensesPool(); $sql = "SELECT l.key_number, l.source, lt.license_type_hash FROM APSLicenses l, APSLicenseTypes lt WHERE l.license_type_id = lt.id"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( my $ptrRow = $self->{dbh}->fetchrow() ) { $self->{packer}->addServerAppLicense( $ptrRow->[0], $ptrRow->[2], $ptrRow->[1] ); } } $self->{dbh}->finish(); } else{ my $distrib_path = AgentConfig::get("PRODUCT_ROOT_D") . "/admin/smb/application/apspackages/"; $self->{packer}->addApsCache($distrib_path) if !$self->{configuration_dump} ; } } if ( PleskVersion::atLeast( 8, 3, 0 ) ) { unless ( PleskVersion::atLeast( 10, 0, 0 ) and not PleskVersion::isSmb() ) { # SiteBuilder Config $sql = "SELECT * FROM SBConfig"; if ( $self->{dbh}->execute_rownum($sql) ) { my @config; while ( my $ptrHash = $self->{dbh}->fetchhash() ) { push @config, $ptrHash; } $self->{packer}->setServerSBConfig( \@config ); } $self->{dbh}->finish(); } } $self->{packer}->setServerBackupSettings( \%params ); $self->dumpServerPreferences( \%params ); $self->makeSpamassassinNode(undef, "*", "*", undef, undef); # Server wide grey-listing preferences my (%glParams, $row); if ( $self->{dbh}->execute_rownum('SELECT param, value FROM GL_settings') ) { while ( $row = $self->{dbh}->fetchrow() ) { $glParams{ $row->[0] } = $row->[1]; } } $self->{dbh}->finish(); $self->{dbh}->execute_rownum('SELECT * FROM GL_remote_domains'); while ( $row = $self->{dbh}->fetchrow() ) { push @{$glParams{ 'white_domains' }}, $row->[0] if $row->[1] eq 'white' ; push @{$glParams{ 'black_domains' }}, $row->[0] if $row->[1] eq 'black'; } $self->{dbh}->finish(); $glParams{'personal-conf'} = defined($params{'spamfilter_use_mailuser_prefs'}) ? $params{'spamfilter_use_mailuser_prefs'} : "false"; $self->{packer}->setGLServerSettings(\%glParams); my $virusfilterNode = $self->{packer}->addServerVirusfilter($params{'virusfilter'}); if ($params{'virusfilter'} eq 'kav') { $self->setServerVirusfilterKav($virusfilterNode) if defined $virusfilterNode; my $kavSettingsNode = $self->{packer}->addServerKavSettings(); $self->setServerKavSettings($kavSettingsNode) if defined $kavSettingsNode; } if (PleskVersion::atLeast(10, 0, 0) and not PleskVersion::isSmb()) { $self->{packer}->setServerColdFusion(\%params); } if (PleskVersion::atLeast(10, 0, 0) and not PleskVersion::isSmb()) { $self->{packer}->setServerGappsInfo(\%params); } if (PleskVersion::atLeast(10, 0, 0) and not PleskVersion::isSmb()) { #Dump event handler $self->{dbh}->execute_rownum('SELECT * FROM actions'); my @actions; while (my $ptrHash = $self->{dbh}->fetchhash()) { push @actions, $ptrHash; } $self->{dbh}->finish(); $self->{dbh}->execute_rownum('SELECT a.name, eh.priority, eh.user, eh.command, eh.action_id FROM event_handlers eh, actions a WHERE eh.action_id = a.id'); my %events; while (my $ptrHash = $self->{dbh}->fetchhash()) { push @{$events{$ptrHash->{'action_id'}}}, $ptrHash; } $self->{dbh}->finish(); $self->{packer}->setServerEventHandler(\%events, \@actions, \%params); } if (PleskVersion::atLeast(10, 0, 0) and not PleskVersion::isSmb()) { $self->{packer}->addServerSiteIsolationConfig(); $self->dumpServerNotifications(); $self->{packer}->addServerMailmanConfiguration(); } if (PleskVersion::atLeast(10, 1, 0) and not PleskVersion::isSmb()) { $self->{packer}->makeBrandingThemeNode('admin', undef); } } sub dumpServerNotifications { my ( $self ) = @_; my $expirationWarnDays = 1; my $sql = "SELECT val FROM misc WHERE param = 'exp_warn_time'"; if ( $self->{dbh}->execute_rownum($sql) and my $ptrRow = $self->{dbh}->fetchrow() ){ $expirationWarnDays = $ptrRow->[0]; } $self->{dbh}->finish(); my @notifications; $sql = "SELECT * FROM Notifications"; if ( $self->{dbh}->execute_rownum($sql) ) { while (my $ptrHash = $self->{dbh}->fetchhash()) { push @notifications, $ptrHash; } } $self->{dbh}->finish(); my %notes; $sql = "SELECT id, text FROM Notes"; if ( $self->{dbh}->execute_rownum($sql) ) { while (my $ptrRow = $self->{dbh}->fetchrow()) { $notes{ $ptrRow->[0] } = $ptrRow->[1]; } } $self->{dbh}->finish(); $self->{packer}->addServerNotifications( $expirationWarnDays, \@notifications, \%notes ); } sub dumpServerPreferences { my ( $self, $params ) = @_; $self->{packer}->addServerPreferences( $params ); if (PleskVersion::atLeast(9, 0, 0) and not PleskVersion::isSmb()) { my $sql = "SELECT type, netaddr, netmask FROM cp_access"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( my $ptrRow = $self->{dbh}->fetchrow() ) { $self->{packer}->addRestrictionItem( $ptrRow->[0], $ptrRow->[1], $ptrRow->[2] ); } } $self->{dbh}->finish(); } if ( PleskVersion::atLeast(10, 1, 0) and not PleskVersion::isSmb()) { if (defined($params->{'disable_mail_ui'})) { $self->{packer}->addDisableMailUiOption($params->{'disable_mail_ui'}); } if (defined($params->{'crontab_secure_shell'}) || defined($params->{'crontab_secure_shell_compatibility_mode'})) { $self->{packer}->addCrontabSecureSettings($params); } } } sub setServerVirusfilterKav() { my ( $self, $virusfilterNode ) = @_; my $table; my $sql = "SHOW TABLES LIKE 'module_kav_parameters'"; if ( $self->{dbh}->execute_rownum( $sql ) and $self->{dbh}->fetchrow() ) { $table = 1; } $self->{dbh}->finish(); if ( $table ) { my %parameters; my %db2xmlAttr = ( 'server_scan_direction' => 'state', 'allow_custom_settings' => 'allow-personal' ); my %db2xmlValue = ( 'server_scan_direction' => { 'any' => 'inout', 'incoming' => 'in', 'outgoing' => 'out', 'none' => 'none' }, 'allow_custom_settings' => { 'yes' => 'both', 'no' => 'none', } ); $sql = "SELECT param, val FROM module_kav_parameters WHERE param='allow_custom_settings' OR param='server_scan_direction'"; if ( $self->{dbh}->execute_rownum( $sql ) ) { while ( my $row = $self->{dbh}->fetchrow() ) { $parameters{$row->[0]} = $row->[1]; } } $self->{dbh}->finish(); foreach my $key (keys %parameters) { if ( exists $db2xmlAttr{$key} && exists $db2xmlValue{$key} && exists ($db2xmlValue{$key}{$parameters{$key}}) ) { $virusfilterNode->setAttribute($db2xmlAttr{$key}, $db2xmlValue{$key}{$parameters{$key}} ); } } } return $virusfilterNode; } sub setServerKavSettings() { my ( $self, $kavSettingsNode ) = @_; my $table; my $sql = "SHOW TABLES LIKE 'module_kav_groups'"; if ( $self->{dbh}->execute_rownum( $sql ) and $self->{dbh}->fetchrow() ) { $table = 1; } $self->{dbh}->finish(); if ( $table ) { my $groupSettings; $sql = "SELECT settings FROM module_kav_groups WHERE name='server_default'"; if ( $self->{dbh}->execute_rownum( $sql ) and my $row = $self->{dbh}->fetchrow() ) { $groupSettings = $row->[0]; } $self->{dbh}->finish(); my %allowedParams = ( 'Check' => 1, 'AddXHeaders' => 1, 'AdminAddress' => 1, 'QuarantinePath' => 1, 'FilterByName' => 1, 'FilterByMIME' => 1, 'SkipByName' => 1, 'SkipByMIME' => 1, 'Quarantine' => 1, 'AdminNotify' => 1, 'AdminAction' => 1, 'SenderNotify' => 1, 'RecipientNotify' => 1, 'RecipientAttachReport' => 1, 'RecipientAction' => 1, 'CuredAdminAction' => 1, 'CuredRecipientAction' => 1, 'InfectedAdminAction' => 1, 'SuspiciousAdminAction' => 1, 'InfectedRecipientAction' => 1, 'SuspiciousRecipientAction' => 1, 'FilteredRecipientAction' => 1, 'FilteredQuarantine' => 1 ); my @groupSettingsArray = split(/\n+/, $groupSettings); if ( @groupSettingsArray ) { foreach my $setting ( @groupSettingsArray ) { if ($setting =~ /(\S*)=(.*)/) { my $param = $1; my $val = $2; if ( $allowedParams{$param} ) { $kavSettingsNode->addChild( XmlNode->new( 'param', 'content' => $val, 'attributes' => { 'name' => $param } ) ); } } } } } return $kavSettingsNode; } sub parseApsIndexFile() { my ( $self, $file ) = @_; my %xmlHash; my $name; if ( open( FILE, $file ) ) { while () { chomp; if ( $_ =~ /<([A-Za-z\-]*)\s+name=\"(.*)\">/ ) { $name = $2; } elsif ( $_ =~ /<([A-Za-z\-]*)>(.*)<\/([A-Za-z\-]*)>/ ) { push @{ $xmlHash{$name} }, $2 unless $1 eq "valid"; } } close FILE; } else { Logging::info( "Aps index file " . $file . " is not exists. Skipping."); } return %xmlHash; } sub getApsArchiveFileName() { my ( $self, $distrib_path, $package_info ) = @_; my %mapHash = $self->parseApsIndexFile( $distrib_path . "/archive-index.xml" ); my $file_name; foreach my $tfile_name ( keys %mapHash ) { if ( $package_info eq join( "-", @{ $mapHash{$tfile_name} } ) ) { $file_name = $tfile_name; } } return $file_name; } sub getDomainKeysDomainSupport() { my ( $self, $domainId, $domainName, $dnsZoneId ) = @_; my $sql = "SELECT p.value FROM Parameters p, DomainServices ds " . "WHERE ds.parameters_id = p.id AND ds.dom_id = $domainId AND p.parameter = 'domain_keys_sign'"; my ($state, $rowPtr); unless ( ( $self->{dbh}->execute_rownum($sql) ) && ( $rowPtr = $self->{dbh}->fetchrow() ) ) { $self->{dbh}->finish(); return; } $state = @{ $rowPtr }[0]; $self->{dbh}->finish(); my $publickKey; $sql = "SELECT * FROM dns_recs WHERE dns_zone_id=$dnsZoneId AND displayHost='default._domainkey.$domainName.'"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( my $ptrHash = $self->{dbh}->fetchhash() ) { chop $ptrHash->{'val'}; $publickKey = substr( $ptrHash->{'val'}, 2 ); } } $self->{dbh}->finish(); $self->{packer}->setDomainKeysDomainSupport( $domainId, $domainName, $state, '/etc/domainkeys/' . $domainName, $publickKey ); } sub getOldWebMailStatus() { my ($self, $ptrDomain) = @_; my $sql; my $retCode = undef; if (PleskVersion::atLeast( 8, 0, 0 )) { my $dnsZoneId = $ptrDomain->{'dns_zone_id'}; $sql = "SELECT * FROM dns_recs WHERE dns_zone_id=$dnsZoneId"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( my $ptrHash = $self->{dbh}->fetchhash() ) { if ($ptrHash->{'displayHost'} =~ /.*webmail.*/) { $retCode = 1; } } } $self->{dbh}->finish(); return $retCode; }else{ my $domainId = $ptrDomain->{'id'}; $sql = "SELECT * FROM dns_recs WHERE dom_id=$domainId"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( my $ptrHash = $self->{dbh}->fetchhash() ) { if ($ptrHash->{'host'} =~ /.*webmail.*/) { $retCode = 1; } } } $self->{dbh}->finish(); return $retCode; } } sub addAllRoles { my ($self) = @_; my $sql = "SELECT id, name, isBuiltIn FROM smb_roles"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( my $ptrHash = $self->{dbh}->fetchhash() ) { my $roleId = $ptrHash->{'id'}; my %permissions = $self->getRolePermissions($roleId); $self->{packer}->addRootRole( $ptrHash->{'name'}, $ptrHash->{'isBuiltIn'}, \%permissions); } } $self->{dbh}->finish(); } sub getRolePermissions { my ($self, $roleId) = @_; my %permissions; my $sql = "SELECT smb_generalPermissions.code, smb_roleGeneralPermissions.isAllowed FROM smb_roles " . "INNER JOIN smb_roleGeneralPermissions ON smb_roles.id = smb_roleGeneralPermissions.roleId " . "INNER JOIN smb_generalPermissions ON smb_generalPermissions.id = smb_roleGeneralPermissions.generalPermissionId " . "WHERE smb_roles.id = '$roleId' "; if ( $self->{dbh}->execute_rownum($sql) ) { while ( my $ptrHash = $self->{dbh}->fetchhash() ) { $permissions{$ptrHash->{'code'}} = $ptrHash->{'isAllowed'}; } } $self->{dbh}->finish(); return %permissions; } sub addAllUsers { my ($self) = @_; my $sql = "SELECT login FROM smb_users"; if ( $self->{dbh}->execute_rownum($sql) ) { while ( my $ptrHash = $self->{dbh}->fetchhash() ) { my $userLogin = $ptrHash->{'login'}; my $userHash = $self->getUserHash($userLogin); $self->{packer}->addRootUser($userLogin, $userHash) if $userHash; } } $self->{dbh}->finish(); } sub getUserHash { my ($self, $user) = @_; my $hashPtr; my $sql = "SELECT smb_users.*, smb_roles.name AS SmbRoleName " . "FROM smb_users INNER JOIN smb_roles ON smb_users.roleId = smb_roles.id " . "WHERE smb_users.login = '$user'"; if ( $self->{dbh}->execute_rownum($sql) ) { $hashPtr = $self->{dbh}->fetchhash(); } $self->{dbh}->finish(); return $hashPtr; } sub getPanelMode { my ($self) = @_; my $mode; my $sql = "SELECT val FROM misc WHERE param = 'power_user_panel'"; if ( $self->{dbh}->execute_rownum($sql) and my $ptrRow = $self->{dbh}->fetchrow()) { $mode = $ptrRow->[0] eq 'true' ? 'PowerUser' : undef; } $self->{dbh}->finish(); return $mode; } sub dumpApsBundle { my ($self, $parentId, $parentType) = @_; my $filterType; my $properties = $self->getSubscriptionPropertiesHash($parentId, $parentType); my $filterId = $properties->{'aps_bundle_filter_id'}; if ($filterId eq '') { return; } my $sql = "SELECT type FROM smb_apsBundleFilters WHERE id = '$filterId'"; if ( $self->{dbh}->execute_rownum($sql) and my $ptrRow = $self->{dbh}->fetchrow()) { $filterType = $ptrRow->[0]; } $self->{dbh}->finish(); $sql = "SELECT propertyName, propertyValue FROM smb_apsBundleFilterItems WHERE filterId = '$filterId'"; my @items; if ($self->{dbh}->execute_rownum($sql)) { while(my $ptrHash = $self->{dbh}->fetchhash()) { push @items, {$ptrHash->{'propertyName'} => $ptrHash->{'propertyValue'}} ; } } $self->{dbh}->finish(); $self->{packer}->makeApsBundleFilterNode($parentId, $parentType, $filterType, \@items, undef); } sub fillDefaultClientPermissions { my $self = @_; my %permissions; unless (PleskVersion::atLeast(10, 0, 0)) { %permissions = %defaultClientPermissions; } return \%permissions; } sub fillDefaultDomainPermissions { my $self = @_; my %permissions; unless (PleskVersion::atLeast(10, 0, 0)) { %permissions = %defaultDomainPermissions; } return \%permissions; } 1; # Local Variables: # mode: cperl # cperl-indent-level: 2 # indent-tabs-mode: nil # tab-width: 4 # End: