· 6 years ago · Aug 05, 2019, 09:30 AM
1# Copyright 1999-2017. Plesk International GmbH. All rights reserved.
2package PleskX;
3
4#
5# Agent interface:
6#
7# ::new($storagePolicy, $dumpStatusPolicy, $agentsSharedDir)
8#
9# ->setDumpType(FULL [default] | SHALLOW | CONFIGURATION | ONLY_MAIL)
10#
11# ->selectDomains(@domains)
12# ->selectClients(@clients)
13# ->selectAll()
14# ->selectAllDomains()
15# ->selectServerSettings()
16#
17# ->excludeDomains(@domains)
18# ->excludeClients(@clients)
19#
20# ->dump()
21#
22# Plesk agent interface:
23#
24# ->setDescription()
25#
26
27use strict;
28use warnings;
29
30use PleskVersion;
31use PleskMaxVersion;
32use PleskStructure;
33use Status;
34use SiteApp;
35use Mailman;
36use AgentConfig;
37use DAL;
38use CommonPacker;
39use StopWatch;
40use Logging;
41use HelpFuncs;
42use Db::DbConnect;
43use Db::Connection;
44use Db::MysqlUtils;
45use Db::PostgresqlUtils;
46use ObjectsFilter;
47use MiscConfigParser;
48use Encode;
49use Suspend;
50
51use XmlLogger;
52
53use vars qw|@ISA|;
54use vars qw|$FULL $SHALLOW $CONFIGURATION $ONLY_MAIL $ONLY_HOSTING $INCLUDE_APP_DISTRIB $NO_LICENSE %listOfInstalledApplicationsOnServer|;
55$FULL = 0;
56$SHALLOW = 1;
57$CONFIGURATION = 2;
58$ONLY_MAIL = 4;
59$ONLY_HOSTING = 8;
60$INCLUDE_APP_DISTRIB = 16;
61$NO_LICENSE = 32;
62
63sub new {
64 my $self = {};
65 bless( $self, shift );
66 $self->_init(@_);
67 return $self;
68}
69
70# --- Public instance methods ---
71sub _init {
72 my ( $self, $storagePolicy, $dumpStatusPolicy, $agentsSharedDir, $backupParameters, $sessionPath ) = @_;
73
74 $self->{collectStatistics} = $self->getCollectStatistics();
75 if ($self->{collectStatistics})
76 {
77 $self->{stopWatch} = StopWatch->new();
78 $self->{stopWatch}->createMarker("all");
79
80 use StopWatchPacker;
81 $self->{packer} = StopWatchPacker->new( PleskMaxVersion::get(), $storagePolicy );
82 }
83 else
84 {
85 use Packer;
86 $self->{packer} = Packer->new( PleskMaxVersion::get(), $storagePolicy );
87 }
88 $self->{dump_status} = $dumpStatusPolicy;
89 $self->{configuration_dump} = undef;
90 $self->{shallow_dump} = undef;
91 $self->{only_mail_dump} = undef;
92 $self->{only_hosting_dump} = undef;
93 $self->{description} = undef;
94 $self->{dump_vhost} = 0;
95 $self->{dump_full_mail} = 0;
96 $self->{admin_info} = 0;
97 $self->{server_settings} = 0;
98 $self->{dumped_domains} = [];
99 $self->{dumped_clients} = [];
100 $self->{existing_remote_db_servers} = [];
101 $self->{suspender} = Suspend->new();
102 $self->{backupParameters} = $backupParameters;
103 $self->{sessionPath} = $sessionPath;
104 $self->{extension_id} = undef;
105 $self->{extension_context_file} = undef;
106 $self->{extension_data} = undef;
107 $self->{markers} = [];
108 $self->{includeFiles} = ['']; # include all
109 $self->{includeDatabases} = undef; # include all
110
111 # domain name => remote web node id
112 # domain name => undef if local
113 $self->{remoteWebNodes} = ();
114
115 AgentConfig::init()
116 or die "Error: Plesk config file 'psa.conf' is not found\n";
117 AgentConfig::setSharedDir($agentsSharedDir);
118
119 AgentConfig::tarBin(); # Pre-caching of values
120 AgentConfig::mysqlBin();
121
122 PleskVersion::init( AgentConfig::get('PRODUCT_ROOT_D') );
123
124 if (defined $self->{backupParameters} && defined $self->{backupParameters}->{db}) {
125 $self->{dbh} = Db::Connection::getConnection(#host port dbType dbName login password
126 'type' => 'mysql',
127 'user' => $self->{backupParameters}->{db}->{username},
128 'password' => $self->{backupParameters}->{db}->{password},
129 'name' => $self->{backupParameters}->{db}->{dbname},
130 'host' => $self->{backupParameters}->{db}->{host},
131 'port' => (defined($self->{backupParameters}->{db}->{port}) ? $self->{backupParameters}->{db}->{port} : "3306"),
132 'utf8names' => 1,
133 'connRetries' => AgentConfig::getMaxDbConnectionsRetries()
134 );
135 } else {
136 $self->{dbh} = Db::Connection::getConnection(
137 'type' => 'mysql',
138 'user' => 'admin',
139 'password' => AgentConfig::get('password'),
140 'name' => 'psa',
141 'host' => 'localhost',
142 'utf8names' => 1,
143 'connRetries' => AgentConfig::getMaxDbConnectionsRetries()
144 );
145 }
146
147 die "Can not connect to the 'psa' database. Please, check database server is running and connection settings are valid" if (!$self->{dbh});
148
149 if ($self->{collectStatistics})
150 {
151 $self->{dbh}->startCollectStatistics();
152 }
153
154 DAL::init( $self->{dbh} );
155
156 PleskStructure::init( $self->{dbh} );
157
158 Encoding::setDefaultEncoding("UTF-8");
159
160 $self->{filter} = ObjectsFilter->new( $self );
161
162 $self->{has_remote_db_server} = 0;
163
164 foreach my $ptrHash (@{DAL::getDatabaseServers()}) {
165 if (HelpFuncs::isRemoteHost($ptrHash->{'host'})) {
166 $self->{has_remote_db_server} = 1;
167 last;
168 }
169 }
170}
171
172sub getCollectStatistics {
173 my $envVal = $ENV{'COLLECT_BACKUP_STAT'};
174 if ($envVal)
175 {
176 return $envVal;
177 }
178 return 0;
179}
180
181sub setDecryptFullDump {
182 my ($self) = @_;
183 $self->{packer}->setDecryptFullDump();
184}
185
186sub setDumpWholeVHost{
187 my ($self) = @_;
188 $self->{dump_vhost} = 1;
189}
190
191sub setDumpWholeMail{
192 my ($self) = @_;
193 $self->{dump_full_mail} = 1;
194}
195
196sub setContentTransport{
197 my $self = shift;
198 my $contentTransportType = shift;
199 $self->{packer}->setContentTransport($contentTransportType, @_)
200}
201
202sub setBackupProfileFileName{
203 my ($self, $profileName, $profileId ) = @_;
204 die "Invalid backup profile name '$profileName'\n" if index( $profileName, '/' )>=0;
205 $self->{packer}->setBackupProfileFileName( $profileName, $profileId ) if $profileName;
206}
207
208sub setIncrementalCreationDate{
209 my ($self, $incrementalCreationDate) = @_;
210 $self->{packer}->setIncrementalCreationDate($incrementalCreationDate);
211}
212
213sub getIncrementalCreationDate {
214 my ($self) = @_;
215 return $self->{packer}->getIncrementalCreationDate();
216}
217
218sub getCreationDate {
219 my ($self) = @_;
220 return $self->{packer}->getCreationDate();
221}
222
223sub getBackupPrefix {
224 my ($self) = @_;
225 return $self->{packer}->{backupPrefix};
226}
227
228sub setLastIndexPath{
229 my ($self, $lastIndexPath) = @_;
230 $self->{packer}->setLastIndexPath($lastIndexPath);
231}
232
233sub setLastIncrementFile {
234 my ($self, $lastIncrementFile) = @_;
235 $self->{packer}->setLastIncrementFile($lastIncrementFile);
236}
237
238sub setExcludePatternsFile {
239 my ($self, $excludePatternsFile) = @_;
240 $self->{packer}->setExcludePatternsFile($excludePatternsFile);
241}
242
243sub setBackupOwnerGuid{
244 my ($self, $ownerGuid, $ownertype ) = @_;
245 $ownerGuid = PleskStructure::getAdminGuid() if not $ownerGuid;
246 $ownertype = 'server' if not $ownertype;
247 $self->{packer}->setBackupOwnerGuid( $ownerGuid, $ownertype );
248}
249
250sub setExtension{
251 my ($self, $extensionId, $extensionContextFile ) = @_;
252
253 $self->{extension_id} = $extensionId;
254 $self->{extension_context_file} = $extensionContextFile;
255 $self->{extension_data} = DAL::getExtensionDataForBackup($extensionId, $extensionContextFile);
256 return unless defined($self->{extension_data});
257
258 my $marker = $self->{extension_data}->{'marker'}[0];
259 push @{$self->{markers}}, $marker;
260 if (defined($self->{extension_data}->{'file'})) {
261 $self->{includeFiles} = $self->{extension_data}->{'file'};
262 } else {
263 $self->{includeFiles} = []; # include nothing
264 }
265 if (defined($self->{extension_data}->{'db'})) {
266 $self->{includeDatabases} = $self->{extension_data}->{'db'};
267 } else {
268 $self->{includeDatabases} = []; # include nothing
269 }
270}
271
272sub getMarkers{
273 my ($self) = @_;
274 return $self->{markers};
275}
276
277sub getBackupOwnerGuid{
278 my ($self) = @_;
279 $self->{packer}->getBackupOwnerGuid();
280}
281
282sub getClientGuid {
283 my ($self, $name) = @_;
284 return PleskStructure::getClientGuid($name);
285}
286
287sub getClientId {
288 my ($self, $name) = @_;
289 return PleskStructure::getClientId($name);
290}
291
292sub getDomainGuid {
293 my ($self, $name) = @_;
294 my $domainPtr = DAL::getDomainPtr($name);
295 return ($domainPtr->{'guid'}) ? $domainPtr->{'guid'} : '';
296}
297
298sub getDomainId {
299 my ($self, $name) = @_;
300 my $domainPtr = DAL::getDomainPtr($name);
301 return ($domainPtr->{'id'}) ? $domainPtr->{'id'} : '';
302}
303
304sub getDomainAsciiName {
305 my ($self, $name) = @_;
306 my $domainPtr = DAL::getDomainPtr($name);
307 return $domainPtr->{'name'};
308}
309
310sub setDumpType {
311 my ( $self, $type ) = @_;
312
313 if ( $type & $SHALLOW ) { $self->{shallow_dump} = 1; }
314 if ( $type & $CONFIGURATION ) { $self->{configuration_dump} = 1; }
315 if ( $type & $ONLY_MAIL ) {
316 $self->{only_mail_dump} = 1;
317 $self->{only_hosting_dump} = undef;
318 }
319 if ( $type & $ONLY_HOSTING ) {
320 $self->{only_hosting_dump} = 1;
321 $self->{only_mail_dump} = undef;
322 }
323
324 if ( $type & $INCLUDE_APP_DISTRIB) {
325 $self->{include_app_distrib} = 1;
326 }
327
328 if ( $type & $NO_LICENSE ) {
329 $self->{no_license} = 1;
330 }
331}
332
333sub setDescription {
334 my ( $self, $description ) = @_;
335 $self->{description} = $description;
336}
337
338sub setExistingRemoteDbServers {
339 my ( $self, $dbServers ) = @_;
340 $self->{existing_remote_db_servers} = $dbServers;
341}
342
343sub selectDomains {
344 my ( $self, @inputDomains ) = @_;
345 @inputDomains = sort { $a cmp $b } @inputDomains;
346
347 my @pleskDomains = sort { $a cmp $b } PleskStructure::getDomains();
348 my @missingDomains = HelpFuncs::arrayDifference( \@inputDomains, \@pleskDomains );
349
350 if (@missingDomains) {
351 my $msg;
352 my $sitesHash = PleskStructure::getSites();
353 my @sites = keys %{$sitesHash};
354 @sites = sort { $a cmp $b } @sites;
355
356 my @missingDomainsAreSites = HelpFuncs::arrayIntersection(\@missingDomains, \@sites);
357
358 if (@missingDomainsAreSites) {
359 $msg = "The following domains are additional domains: " . ( join ",", @missingDomainsAreSites ) . ".\n";
360 $msg .= "Backups of specified domains will be included in backups of their subscriptions." . "\n";
361 foreach my $site (@missingDomainsAreSites) {
362 $msg .= "Domain '" . $site ."' will be backed up with subscription '" . $sitesHash->{$site} . "'.\n";
363 }
364 } else {
365 $msg = "The following domains were not found on the host: " . ( join ",", @missingDomains );
366 }
367 print STDERR "$msg\n";
368 Logging::warning( $msg, 'MissingDomains' );
369 @inputDomains = HelpFuncs::arrayIntersection( \@inputDomains, \@pleskDomains );
370 }
371 $self->{domains} = \@inputDomains if @inputDomains;
372}
373
374sub selectDomainsById {
375 my ( $self, @inputDomains ) = @_;
376
377 my @pleskDomains = PleskStructure::getDomainsFromId( \@inputDomains );
378 if( @inputDomains ){
379 my $msg = "The following domain id's were not found on the host: " . ( join ",", @inputDomains );
380 print STDERR "$msg\n";
381 Logging::warning( $msg, 'MissingDomains' );
382 }
383 $self->selectDomains( @pleskDomains ) if @pleskDomains;
384}
385
386sub selectClients {
387 my ( $self, @inputClients ) = @_;
388 @inputClients = sort { $a cmp $b } @inputClients;
389
390 my @pleskClients = sort { $a cmp $b } PleskStructure::getClients();
391 my @missingClients = HelpFuncs::arrayDifference( \@inputClients, \@pleskClients );
392
393 if (@missingClients) {
394 my $msg = "The following clients were not found on the host: " . ( join ",", @missingClients );
395 print STDERR "$msg\n";
396 Logging::warning( $msg, 'MissingClients' );
397 @inputClients = HelpFuncs::arrayIntersection( \@inputClients, \@pleskClients );
398 }
399 $self->_selectClients( \@inputClients ) if @inputClients;
400}
401
402sub selectClientsById {
403 my ( $self, @inputClients ) = @_;
404
405 my @pleskClients = PleskStructure::getClientsFromId( \@inputClients);
406 if( @inputClients ){
407 my $msg = "The following clients id's were not found on the host: " . ( join ",", @inputClients );
408 print STDERR "$msg\n";
409 Logging::warning( $msg, 'MissingClients' );
410 }
411 $self->selectClients( @pleskClients ) if @pleskClients;
412}
413
414sub selectResellers {
415 my ( $self, @inputResellers ) = @_;
416 @inputResellers = sort { $a cmp $b } @inputResellers;
417
418 my @pleskResellers = sort { $a cmp $b } PleskStructure::getResellers();
419 my @missingResellers = HelpFuncs::arrayDifference( \@inputResellers, \@pleskResellers );
420
421 if (@missingResellers) {
422 my $msg = "The following resellers were not found on the host: " . ( join ",", @missingResellers );
423 print STDERR "$msg\n";
424 Logging::warning( $msg, 'MissingResellers' );
425 @inputResellers = HelpFuncs::arrayIntersection( \@inputResellers, \@pleskResellers );
426 }
427 $self->_selectClients( \@inputResellers ) if @inputResellers;
428}
429
430sub selectResellersById {
431 my ( $self, @inputResellers ) = @_;
432
433 my @pleskResellers = PleskStructure::getResellersFromId( \@inputResellers);
434 if( @inputResellers ){
435 my $msg = "The following reseller id's were not found on the host: " . ( join ",", @inputResellers );
436 print STDERR "$msg\n";
437 Logging::warning( $msg, 'MissingResellers' );
438 }
439 $self->selectResellers( @pleskResellers ) if @pleskResellers;
440}
441
442sub _selectClients {
443 my( $self, $logins ) = @_;
444 my @clients;
445 my @resellers;
446 my $admin = 0;
447 foreach my $client(@{$logins}){
448 my $clType = PleskStructure::getClientType( $client );
449 push @clients, $client if $clType eq 'client';
450 push @resellers, $client if $clType eq 'reseller';
451 $admin = 1 if $clType eq 'admin';
452 }
453 $self->{resellers} = \@resellers if (@resellers);
454 $self->{clients} = \@clients if (@clients);
455 $self->{dump_all} = 1 if $admin;
456}
457
458sub excludeDomains {
459 my ( $self, @inputDomains ) = @_;
460 @inputDomains = PleskStructure::getDomains() if scalar(@inputDomains)==0;
461 @inputDomains = sort { $a cmp $b } @inputDomains;
462
463 $self->{exclude_domains} = \@inputDomains;
464 $self->{domains} = [HelpFuncs::arrayDifference($self->{domains}, \@inputDomains)] if exists $self->{domains};
465}
466
467sub excludeClients {
468 my ( $self, @inputClients ) = @_;
469 @inputClients = PleskStructure::getClients() if scalar(@inputClients)==0;
470 @inputClients = sort { $a cmp $b } @inputClients;
471
472 $self->{exclude_clients} = \@inputClients;
473 $self->{clients} = [HelpFuncs::arrayDifference($self->{clients}, \@inputClients)] if exists $self->{clients};
474}
475
476sub excludeResellers {
477 my ( $self, @inputResellers ) = @_;
478 @inputResellers = PleskStructure::getResellers() if scalar(@inputResellers)==0;
479 @inputResellers = sort { $a cmp $b } @inputResellers;
480
481 $self->{exclude_resellers} = \@inputResellers;
482 $self->{resellers} = [HelpFuncs::arrayDifference($self->{resellers}, \@inputResellers)] if exists $self->{resellers};
483}
484
485sub domainExcluded{
486 my ($self, $name ) = @_;
487 if( exists $self->{exclude_domains} ){
488 foreach my $domain( @{$self->{exclude_domains}} ){
489 return 1 if $domain eq $name;
490 }
491 }
492 return 0;
493}
494
495sub clientExcluded{
496 my ($self, $name ) = @_;
497 if( exists $self->{exclude_clients} ){
498 foreach my $client( @{$self->{exclude_clients}} ){
499 return 1 if $client eq $name;
500 }
501 }
502 return 0;
503}
504
505sub resellerExcluded{
506 my ($self, $name ) = @_;
507 if( exists $self->{exclude_resellers} ){
508 foreach my $reseller( @{$self->{exclude_resellers}} ){
509 return 1 if $reseller eq $name;
510 }
511 }
512 return 0;
513}
514
515sub selectAll {
516 my ($self) = @_;
517 $self->{dump_all} = 1;
518}
519
520sub selectAllResellers {
521 my ($self) = @_;
522
523 my @pleskResellers = sort { $a cmp $b } PleskStructure::getResellers();
524 $self->{resellers} = \@pleskResellers;
525}
526
527sub selectAllClients {
528 my ($self) = @_;
529
530 my @pleskClients = sort { $a cmp $b } PleskStructure::getClients();
531 $self->{clients} = \@pleskClients;
532}
533
534sub selectAllDomains {
535 my ($self) = @_;
536
537 my @pleskDomains = sort { $a cmp $b } PleskStructure::getDomains();
538 $self->{domains} = \@pleskDomains;
539}
540
541sub selectServerSettings {
542 my ($self) = @_;
543 $self->{server_settings} = 1;
544 Logging::debug( "Select to backup server settings" );
545}
546
547sub selectAdminInfo {
548 my ($self) = @_;
549 $self->{admin_info} = 1;
550 Logging::debug( "Select to backup Administrator info" );
551}
552
553sub setSuspend{
554 my ( $self, $suspend, $suspendSid ) = @_;
555 $self->{suspender}->setSuspend($suspend, $suspendSid);
556}
557
558sub Cleanup{
559 my $self = shift;
560 $self->{suspender}->unSuspendDomain();
561}
562
563sub getListOfInstalledApplicationsOnServer {
564 my ($self) = @_;
565
566 if (scalar keys %listOfInstalledApplicationsOnServer == 0) {
567 my @serverApplications = SiteApp::getServerSettingsForApplications();
568 if (@serverApplications) {
569 foreach my $ptrRow ( @{DAL::getApsPackages103()} ) {
570 my $application = $self->getConcreteApplicationInfo(\@serverApplications, $ptrRow->[6]);
571 if (!$application) {
572 Logging::debug("Can't get '$ptrRow->[0]-$ptrRow->[1]-$ptrRow->[2]' application info by '$ptrRow->[6]'", 'SiteappError');
573 next;
574 }
575
576 my $packageArchive = $application->getPackageArchive();
577 my $packageArchiveFileName = undef;
578 my $packageArchiveDir = undef;
579
580 my $idx = rindex( $packageArchive, '/' );
581
582 if ( $idx > 0 ) {
583 $packageArchiveDir = substr( $packageArchive, 0, $idx);
584 $packageArchiveFileName = substr( $packageArchive, $idx+1);
585 }
586
587 $listOfInstalledApplicationsOnServer{$application->getRegistryUid()} = [$ptrRow->[0], $ptrRow->[1], $ptrRow->[2], $packageArchiveDir, $packageArchiveFileName, $ptrRow->[4], $ptrRow->[5], $application];
588 }
589 }
590 }
591 return \%listOfInstalledApplicationsOnServer;
592}
593
594sub dump {
595 my ($self) = @_;
596
597 $self->checkProgramTerminated();
598
599 Logging::beginObject('server', 'server');
600
601 $self->{packer}->turnOffContent() if $self->{configuration_dump};
602
603 $self->{packer}->setRoot(
604 $self->{description},
605 $self->{configuration_dump} ? 0 : 1,
606 'panel',
607 PleskStructure::getAdminGuid(),
608 DAL::getEmbeddedInfo(['--backup-server-info'])
609 );
610
611 $self->{packer}->setMarkers(@{$self->{markers}});
612
613 my $embeddedInfo = {};
614 if ($self->{server_settings} || $self->{admin_info}) {
615 $embeddedInfo = DAL::getEmbeddedInfo(['--backup-server']);
616 }
617
618 $self->_createLocalDumpNameFile();
619
620 if( exists $self->{dump_all} ) {
621 $self->createFullDump();
622
623 $self->makeAdminInfoNode($embeddedInfo) if $self->{admin_info};
624 eval {
625 $self->makeServerNode($embeddedInfo) if $self->{server_settings};
626 $self->{packer}->addServerNodeToDump();
627 1;
628 } or do {
629 $self->checkProgramTerminated();
630 $self->excludeProblemServerFromBackup( $@ );
631 }
632 }
633 else{
634 my $done;
635 $self->beginWriteStatus();
636 if( $self->{admin_info} or $self->{server_settings} ) {
637 $self->{packer}->addRootAdmin(PleskStructure::getAdminId(), PleskStructure::getAdminGuid(), DAL::getFullHostName());
638 $done = 1;
639 }
640 if (exists $self->{resellers}){
641 $self->createResellersDump();
642 $done = 1;
643 }
644 if (exists $self->{clients}) {
645 $self->createClientsDump();
646 $done = 1;
647 }
648 if ( exists $self->{domains} ) {
649 $self->createDomainsDump();
650 $done = 1;
651 }
652
653 $self->{packer}->addRootRoles();
654 $self->{packer}->addRootUsers();
655 $self->{packer}->addRootDomains();
656 if( $self->{server_settings} ){
657 $self->makeAdminUsersAndRoles();
658 eval {
659 $self->makeServerNode($embeddedInfo);
660 $done = 1;
661 1;
662 } or do {
663 $self->checkProgramTerminated();
664 $self->excludeProblemServerFromBackup( $@ );
665 }
666 }
667 if( $self->{admin_info} ) {
668 $self->makeAdminInfoNode($embeddedInfo);
669 $done = 1;
670 }
671 $self->{packer}->addServerNodeToDump();
672 $self->{dump_status}->finishObjects();
673 if ( not $done ) {
674 Logging::error("No objects to dump found");
675 Logging::endObject();
676 return 1;
677 }
678 }
679
680 $self->{suspender}->unSuspendDomain();
681 my $ret = $self->{packer}->finish();
682
683 if ($self->{collectStatistics})
684 {
685 $self->writeStatistics();
686 }
687
688 Logging::endObject();
689
690 $self->_reportDomainStatistics();
691
692 return $ret;
693}
694
695###### Size mode functions ######
696sub getSize {
697 my ($self, $incrementalBackup, $backupToFtp) = @_;
698
699 use BackupSizeCalculator;
700
701 my $backupSizeCalculator = BackupSizeCalculator->new( $self, $incrementalBackup, $backupToFtp );
702
703 return $backupSizeCalculator->getSize();
704}
705###### End Size mode functions ######
706
707sub writeStatistics {
708 my $self = shift;
709
710 my $logPath = $ENV{'COLLECT_BACKUP_STAT_LOG'};
711 if (!defined($logPath) || length($logPath) == 0)
712 {
713 $logPath = "perfomance-statistics.log";
714 }
715
716 $logPath = ">>" . $logPath;
717
718 open(LOGFILE, $logPath);
719
720 print $logPath;
721
722 print LOGFILE "Date: " . HelpFuncs::getTime() . "\n";
723
724 my $allTime = $self->{stopWatch}->getDiff("all");
725 print LOGFILE "All time: " . $allTime . "\n";
726
727 print LOGFILE "Sql time: " . $self->{dbh}->getStatistics()->{sqlTime} . "\n";
728
729 my $xmlTarTime = $self->{packer}->getStatistics()->{totalTime};
730 my $tarTime = $self->{packer}->getStatistics()->{tarTime};
731
732 print LOGFILE "Xml time: " . ($xmlTarTime - $tarTime) . "\n";
733 print LOGFILE "Files time: " . $tarTime . "\n";
734
735 print LOGFILE "\n";
736
737 close(LOGFILE);
738}
739
740sub getAdminRootPath{
741 my ($self) = @_;
742 return $self->{packer}->regAdminObjectBackupPath( '' );
743}
744
745my %generalRolePermissions = (
746 'userManagement' => 1,
747 'webSitesAndDomainsManagement' => 1,
748 'logRotationManagement' => 1,
749 'anonymousFtpManagement' => 1,
750 'scheduledTasksManagement' => 1,
751 'spamfilterManagement' => 1,
752 'antivirusManagement' => 1,
753 'databasesManagement' => 1,
754 'backupRestoreManagement' => 1,
755 'browseStats' => 1,
756 'applicationsManagement' => 1,
757 'sitebuilderManagement' => 1,
758 'filesManagement' => 1,
759 'ftpAccountsManagement' => 1,
760 'dnsManagement' => 1,
761 'mailManagement' => 1,
762 'mailListsManagement' => 1,
763 'publishFilesOnTheWeb' => 1,
764);
765
766sub getRolePermissions {
767 my ($self, $roleId) = @_;
768
769 my %permissions = %{DAL::getRolePermissions($roleId)};
770 %permissions = map { $_ => $permissions{$_} } grep { $generalRolePermissions{$_} } keys %permissions;
771
772 return \%permissions;
773}
774
775sub _createLocalDumpNameFile {
776 my ($self) = @_;
777
778 return unless ($self->{sessionPath});
779
780 my $filename;
781 if ($self->{dump_all} or $self->{admin_info} or $self->{server_settings}) {
782 $filename = $self->{packer}->getAdminBackupPath('info', 1) . ".xml";
783 } elsif (exists $self->{resellers} and scalar(@{$self->{resellers}}) == 1){
784 my $clientInfo = DAL::getClientShortInfo(@{$self->{resellers}}[0]);
785 $filename = $self->getClientRootPath($self->{resellers}->[0]) . "/" .
786 $self->{packer}->getClientsBackupPath($clientInfo->{id}, 'info', 1) . ".xml";
787 } elsif (exists $self->{clients} and scalar(@{$self->{clients}}) == 1) {
788 my $clientInfo = DAL::getClientShortInfo(@{$self->{clients}}[0]);
789 $filename = $self->getClientRootPath($self->{clients}->[0]) . "/" .
790 $self->{packer}->getClientsBackupPath($clientInfo->{id}, 'info', 1) . ".xml";
791 } elsif (exists $self->{domains} and scalar(@{$self->{domains}}) == 1) {
792 my $domainInfo = DAL::getDomainShortInfo(@{$self->{domains}}[0]);
793 $filename = $self->getDomainRootPath(@{$self->{domains}}[0]) . "/" .
794 $self->{packer}->getDomainsBackupPath($domainInfo->{id}, 'info', 1) . ".xml";
795 } else {
796 $filename = $self->{packer}->getAdminBackupPath('info', 1) . ".xml";
797 }
798
799 open DUMP_RES, "> $self->{sessionPath}/local-dump-name";
800 print DUMP_RES "$filename";
801 close DUMP_RES;
802}
803
804sub createFullDump {
805 my ($self) = @_;
806
807 $self->getAdminRootPath();
808
809 $self->{packer}->addRootAdmin(PleskStructure::getAdminId(), PleskStructure::getAdminGuid(), DAL::getFullHostName());
810
811 $self->{dump_status}->start(PleskStructure::getClientsCount(''), PleskStructure::getDomainsCount( '' ) );
812
813 my @resellers = sort { $a cmp $b } PleskStructure::getResellers();
814 @resellers = $self->{filter}->filterSelectedResellers( \@resellers );
815
816 foreach my $reseller (@resellers) {
817 my @myclients = sort { $a cmp $b } PleskStructure::getMyClients($reseller);
818 @myclients = $self->{filter}->filterSelectedClients( \@myclients );
819 my @domains = sort { $a cmp $b } PleskStructure::getDomainsForClient($reseller);
820 @domains = $self->{filter}->filterSelectedDomains( \@domains );
821 eval {
822 $self->makeClientNode($reseller, \@domains, \@myclients, 0 );
823 1;
824 } or do {
825 $self->checkProgramTerminated();
826 $self->excludeProblemClientFromBackup( $reseller, $@ );
827 }
828 }
829
830 my @clients = sort { $a cmp $b } PleskStructure::getAdminClients();
831
832 foreach my $client (@clients) {
833 if( PleskStructure::getClientType( $client ) eq 'client' ){
834 my @myclients = sort { $a cmp $b } PleskStructure::getMyClients($client);
835 @myclients = $self->{filter}->filterSelectedClients( \@myclients );
836 my @domains = sort { $a cmp $b } PleskStructure::getDomainsForClient($client);
837 @domains = $self->{filter}->filterSelectedDomains( \@domains );
838 eval {
839 $self->makeClientNode($client, \@domains, \@myclients, 0 );
840 1;
841 } or do {
842 $self->checkProgramTerminated();
843 $self->excludeProblemClientFromBackup( $client, $@ );
844 }
845 }
846 }
847
848 if (exists($self->{dump_all}) && !$self->{server_settings}) {
849 my $adminId = PleskStructure::getAdminId();
850 $self->dumpTemplates($adminId, 'server', 'reseller');
851 }
852
853 my $adminName = PleskStructure::getAdminName();
854 $self->{dump_status}->startClient($adminName);
855
856 my @adminDomains = PleskStructure::getAdminDomains();
857 @adminDomains = $self->{filter}->filterSelectedDomains( \@adminDomains );
858 foreach my $domainName(@adminDomains) {
859 eval {
860 $self->makeDomainNode($domainName, 0 );
861 1;
862 } or do {
863 $self->checkProgramTerminated();
864 $self->excludeProblemDomainFromBackup($domainName, $@);
865 };
866 }
867
868 $self->makeAdminUsersAndRoles();
869
870 $self->{dump_status}->endClient($adminName);
871
872 $self->{dump_status}->finishObjects();
873}
874
875sub excludeProblemClientFromBackup {
876 my ( $self, $clientName, $reason ) = @_;
877
878 my $clientType = PleskStructure::getClientType( $clientName );
879 my $clientId = PleskStructure::getClientId( $clientName );
880
881 Logging::warning( "$clientType $clientName is skipped from backup due to error: $reason" );
882 Logging::debug( "$clientType $clientName is skipped from backup due to error: $reason", 'fatal' );
883
884 if ( $clientType eq 'client' ) {
885 delete $self->{packer}->{clientNodes}->{$clientId};
886 } elsif ( $clientType eq 'reseller' ) {
887 delete $self->{packer}->{resellerNodes}->{$clientId};
888 }
889}
890
891sub excludeProblemDomainFromBackup {
892 my ( $self, $domainName, $reason ) = @_;
893
894 Logging::warning( "Domain $domainName is skipped from backup due to error: $reason" );
895 Logging::debug( "Domain $domainName is skipped from backup due to error: $reason", 'fatal' );
896
897 my $domainId = PleskStructure::getDomainId( $domainName );
898 delete $self->{packer}->{domainNodes}->{$domainId};
899 delete $self->{packer}->{domainShortNodes}->{$domainId};
900
901 $self->{suspender}->unSuspendDomain();
902}
903
904sub excludeProblemSiteFromBackup {
905 my ( $self, $domainId, $ptrSite, $reason ) = @_;
906
907 Logging::warning( "Domain $ptrSite->{'name'} is skipped from backup due to error: $reason" );
908 Logging::debug( "Domain $ptrSite->{'name'} is skipped from backup due to error: $reason", 'fatal' );
909
910 $self->{packer}->removeSiteNode( $domainId, $ptrSite->{'name'} );
911
912 $self->{suspender}->unSuspendDomain();
913}
914
915sub excludeProblemDatabaseFromBackup {
916 my ( $self, $domainId, $db, $reason ) = @_;
917
918 Logging::warning( "Database $db->{'name'}, type $db->{'type'} is skipped from backup due to error: $reason" );
919 Logging::debug( "Database $db->{'name'}, type $db->{'type'} is skipped from backup due to error: $reason", 'fatal' );
920
921 $self->{packer}->removeDatabaseNode( $domainId, $db );
922}
923
924sub excludeProblemServerFromBackup {
925 my ( $self, $reason ) = @_;
926
927 Logging::warning( "Server settings are skipped from backup due to error: $reason" );
928 Logging::debug( "Server settings are skipped from backup due to error: $reason", 'fatal' );
929
930 $self->{packer}->removeServerNode();
931}
932
933sub excludeProblemMailUserFromBackup {
934 my ( $self, $domainId, $mail, $reason ) = @_;
935
936 my $domainName = PleskStructure::getDomainNameFromId( $domainId );
937 Logging::warning( "Mail user $mail->{'mail_name'} on domain $domainName is skipped from backup due to error: $reason" );
938 Logging::debug( "Mail user $mail->{'mail_name'} on domain $domainName is skipped from backup due to error: $reason", 'fatal' );
939
940 $self->{packer}->removeMailuserNode( $domainId, $mail );
941}
942
943sub excludeProblemMailSystemFromBackup {
944 my ( $self, $domainId, $reason ) = @_;
945
946 my $domainName = PleskStructure::getDomainNameFromId( $domainId );
947
948 Logging::warning( "Mail System on domain $domainName is skipped from backup due to error: $reason" );
949 Logging::debug( "Mail System on domain $domainName is skipped from backup due to error: $reason", 'fatal' );
950
951 $self->{packer}->removeMailSystemNode( $domainId );
952}
953
954sub excludeProblemHostingFromBackup {
955 my ( $self, $domainId, $hostingType, $reason ) = @_;
956
957 my $domainName = PleskStructure::getDomainNameFromId( $domainId );
958
959 Logging::warning( "Hosting on domain $domainName is skipped from backup due to error: $reason" );
960 Logging::debug( "Hosting on domain $domainName is skipped from backup due to error: $reason", 'fatal' );
961
962 $self->{packer}->removeHostingNode( $domainId, $hostingType );
963}
964
965sub excludeProblemDnsZoneFromBackup {
966 my ( $self, $domainId, $reason ) = @_;
967
968 my $domainName = PleskStructure::getDomainNameFromId( $domainId );
969
970 Logging::warning( "DNS Service on domain $domainName is skipped from backup due to error: $reason" );
971 Logging::debug( "DNS Service on domain $domainName is skipped from backup due to error: $reason", 'fatal' );
972
973 $self->{packer}->removeDomainDnsZone($domainId);
974}
975
976sub excludeProblemUserFromBackup {
977 my ( $self, $userLogin, $callback, $reason ) = @_;
978
979 Logging::warning( "User $userLogin is skipped from backup due to error: $reason" );
980 Logging::debug( "User $userLogin is skipped from backup due to error: $reason", 'fatal' );
981
982 $callback->( $userLogin );
983}
984
985sub excludeProblemRoleFromBackup {
986 my ( $self, $callback, $roleName, $reason ) = @_;
987
988 Logging::warning( "Role $roleName is skipped from backup due to error: $reason" );
989 Logging::debug( "Role $roleName is skipped from backup due to error: $reason", 'fatal' );
990
991 $callback->( $roleName );
992}
993
994sub makeAdminLimitsAndPermissions {
995 my ($self) = @_;
996 my $permsHash = $self->getPermsHash(PleskStructure::getAdminId());
997 foreach my $key ( keys %{$permsHash} ) {
998 $self->{packer}->addAdminPermission($key, $permsHash->{$key});
999 }
1000}
1001
1002sub makeAdminUsersAndRoles {
1003 my ( $self ) = @_;
1004
1005 my $adminName = PleskStructure::getAdminName();
1006 my @adminUsersLogins = PleskStructure::getUserLogins( $adminName );
1007
1008 my $callback = sub {
1009 $self->{packer}->addAdminUser( @_ );
1010 };
1011
1012 my $callbackFailed = sub {
1013 $self->{packer}->removeAdminUser( @_ );
1014 };
1015
1016 $self->addUsers( \@adminUsersLogins, $callback, $callbackFailed );
1017
1018 my $callbackRole = sub {
1019 $self->{packer}->removeAdminRole( @_ );
1020 };
1021
1022 for my $roleId ( PleskStructure::getRoleIds( $adminName ) ) {
1023 my @role = grep {$_->{'id'}==$roleId and $_->{'isBuiltIn'}==0 } @{DAL::selectSmbRoles()};
1024 eval {
1025 if ( @role ) {
1026 $self->{packer}->addAdminRole( $role[0]->{'name'}, 0, $self->getRolePermissions($roleId), DAL::getRoleServicePermissions($roleId) ) ;
1027 }
1028 1;
1029 } or do {
1030 $self->excludeProblemRoleFromBackup( $callbackRole, $role[0]->{'name'}, $@ );
1031 }
1032 }
1033}
1034
1035sub getClientRootPath{
1036 my ($self, $clientLogin ) = @_;
1037 my $clientId = PleskStructure::getClientId($clientLogin);
1038 my $clientType = PleskStructure::getClientType($clientLogin);
1039 if( $clientType eq 'reseller' ){
1040 return $self->{packer}->regResellersObjectBackupPath( $self->getAdminRootPath(), $clientId, $clientLogin );
1041 }
1042 elsif( $clientType eq 'client' ){
1043 my $parentId = PleskStructure::getClientParentId( $clientLogin );
1044 my $parentLogin = PleskStructure::getClientNameFromId( $parentId );
1045 return $self->{packer}->regClientObjectBackupPath( $self->getClientRootPath($parentLogin), $clientId, $clientLogin );
1046 }
1047 else{
1048 return $self->getAdminRootPath();
1049 }
1050}
1051
1052sub beginWriteStatus{
1053 my ($self) = @_;
1054 my %accounts;
1055 my %domains;
1056 if( exists $self->{resellers} ){
1057 foreach my $reseller ( @{ $self->{resellers} } ) {
1058 $accounts{$reseller} = 1;
1059 my @myclients = sort { $a cmp $b } PleskStructure::getMyClients($reseller);
1060 @myclients = $self->{filter}->filterSelectedClients( \@myclients );
1061 for my $client( @myclients ){
1062 $accounts{$client} = 1;
1063 }
1064 foreach my $client( @myclients ){
1065 my @mydomains = sort { $a cmp $b } PleskStructure::getDomainsForClient($client);
1066 @mydomains = $self->{filter}->filterSelectedDomains( \@mydomains );
1067 for my $domain( @mydomains ){
1068 $domains{$domain} = 1;
1069 }
1070 }
1071 }
1072 }
1073 if( exists $self->{clients} ){
1074 foreach my $client ( @{ $self->{clients} } ) {
1075 $accounts{$client} = 1;
1076 my @mydomains = sort { $a cmp $b } PleskStructure::getDomainsForClient($client);
1077 @mydomains = $self->{filter}->filterSelectedDomains( \@mydomains );
1078 for my $domain( @mydomains ){
1079 $domains{$domain} = 1;
1080 }
1081 }
1082 }
1083 if( exists $self->{domains} ){
1084 for my $domain( @{$self->{domains}} ){
1085 $domains{$domain} = 1;
1086 }
1087 }
1088
1089 $self->{dump_status}->start( scalar( keys(%accounts) ), scalar( keys( %domains ) ) );
1090}
1091
1092sub createResellersDump{
1093 my ($self) = @_;
1094
1095 my( %clients, %domains );
1096
1097 my $client;
1098 foreach my $reseller ( @{ $self->{resellers} } ) {
1099 my @myclients = sort { $a cmp $b } PleskStructure::getMyClients($reseller);
1100 @myclients = $self->{filter}->filterSelectedClients( \@myclients );
1101 $clients{$reseller} = \@myclients;
1102
1103 my @mydomains = sort { $a cmp $b } PleskStructure::getDomainsForClient($reseller);
1104 @mydomains = $self->{filter}->filterSelectedDomains( \@mydomains );
1105 $domains{$reseller} = \@mydomains;
1106 }
1107
1108 foreach my $reseller ( @{ $self->{resellers} } ) {
1109 $self->getClientRootPath( $reseller );
1110 eval {
1111 $self->makeClientNode($reseller, $domains{$reseller}, $clients{$reseller}, 1 );
1112 1;
1113 } or do {
1114 $self->checkProgramTerminated();
1115 $self->excludeProblemClientFromBackup( $reseller, $@ );
1116 }
1117 }
1118}
1119
1120sub createClientsDump {
1121 my ( $self ) = @_;
1122
1123 my (%clients);
1124 foreach my $client ( @{ $self->{clients} } ) {
1125 my @mydomains = sort { $a cmp $b } PleskStructure::getDomainsForClient($client);
1126 @mydomains = $self->{filter}->filterSelectedDomains( \@mydomains );
1127 $clients{$client} = \@mydomains;
1128 }
1129
1130 foreach my $client (keys %clients) {
1131 $self->getClientRootPath( $client );
1132 eval {
1133 $self->makeClientNode( $client, $clients{$client}, undef, 1 );
1134 1;
1135 } or do {
1136 $self->checkProgramTerminated();
1137 $self->excludeProblemClientFromBackup( $client, $@ );
1138 }
1139 }
1140}
1141
1142sub getDomainRootPathByAscName {
1143 my ($self, $domainAscName) = @_;
1144
1145 my $domainPtr = DAL::getDomainPtrByAsciiName($domainAscName);
1146 return undef unless $domainPtr;
1147 return $self->_getDomainRootPath($domainPtr->{'id'}, $domainPtr->{'cl_id'}, $domainPtr->{'name'});
1148}
1149
1150sub getDomainRootPath{
1151 my ($self, $domainName ) = @_;
1152
1153 my $sql = "SELECT id, cl_id, name FROM domains WHERE displayName = BINARY '?'";
1154 my $ptrHash;
1155 my $domainId;
1156 my $clientId;
1157 my $domainAscName;
1158 if( $self->{dbh}->execute($sql, $domainName) ) {
1159 if ( $ptrHash = $self->{dbh}->fetchhash() ) {
1160 $domainId = $ptrHash->{'id'};
1161 $clientId = $ptrHash->{'cl_id'};
1162 $domainAscName = $ptrHash->{'name'};
1163 }
1164 }
1165 $self->{dbh}->finish();
1166
1167 return $self->_getDomainRootPath($domainId, $clientId, $domainAscName);
1168}
1169
1170sub _getDomainRootPath{
1171 my ($self, $domainId, $clientId, $domainAscName) = @_;
1172
1173 return undef unless $domainId and $clientId and $domainAscName;
1174
1175 my $rootPath = $self->getClientRootPath(PleskStructure::getClientNameFromId($clientId));
1176 return $self->{packer}->regDomainObjectBackupPath($rootPath, $domainId, $domainAscName);
1177}
1178
1179sub createDomainsDump {
1180 my ( $self ) = @_;
1181
1182 foreach my $domainName ( @{$self->{domains}} ) {
1183 if ( $self->getDomainRootPath( $domainName ) ) {
1184 eval {
1185 $self->makeDomainNode( $domainName, 1 );
1186 1;
1187 } or do {
1188 $self->checkProgramTerminated();
1189 $self->excludeProblemDomainFromBackup($domainName, $@);
1190 };
1191 }
1192 else {
1193 my $msg = "Unable to backup domain $domainName because of unappropriate database content";
1194 print STDERR "$msg\n";
1195 Logging::warning( $msg, 'PleskDbError' );
1196 }
1197 }
1198}
1199
1200sub dumpDomainPersonalPermissions {
1201 my ( $self, $domainId, $permId ) = @_;
1202 $self->addPermissions( $domainId, 'domain-personal', $permId );
1203}
1204
1205sub makeClientNode {
1206 my ( $self, $clientName, $domains, $childClients, $isroot ) = @_;
1207
1208 $self->checkProgramTerminated();
1209
1210 my ($parent, $clientType );
1211 $clientType = PleskStructure::getClientType( $clientName );
1212
1213 if( $clientType eq 'client' and $self->clientExcluded( $clientName ) ) {
1214 Logging::debug("Client '$clientName' is excluded from dump");
1215 return;
1216 }
1217 if( $clientType eq 'reseller' and $self->resellerExcluded( $clientName ) ) {
1218 Logging::debug("Reseller '$clientName' is excluded from dump");
1219 return;
1220 }
1221
1222 foreach my $dumpedClient( @{$self->{dumped_clients}} ){
1223 if( $dumpedClient eq $clientName ){
1224 Logging::debug("Client '$dumpedClient' already dumped");
1225 return;
1226 }
1227 }
1228 push @{$self->{dumped_clients}}, $clientName;
1229
1230 my ( $item, $sql, $ptrHash, $value, %client, $ptrRow, $id, %clientParams );
1231 Logging::beginObject($clientType,$clientName, $self->generateObjectUuidForLogging($clientType,$clientName));
1232 Logging::debug("Client '$clientName' is started") if $clientType eq 'client';
1233 Logging::debug("Reseller '$clientName' is started") if $clientType eq 'reseller';
1234 $self->{dump_status}->startClient($clientName);
1235
1236 $sql = "SELECT * FROM clients WHERE login = '?'";
1237
1238 if ( $self->{dbh}->execute($sql, $clientName) ) {
1239 if (my $ptrHash = $self->{dbh}->fetchhash() ) {
1240 %client = %{ $ptrHash };
1241 }
1242 }
1243 $self->{dbh}->finish();
1244
1245 my $clientId = $client{'id'};
1246 $parent = PleskStructure::getClientNameFromId( $client{'parent_id'} ) if exists $client{'parent_id'};
1247 if ( exists $client{'vendor_id'} ){
1248 my $vendorGuid = PleskStructure::getClientGuidFromId( $client{'vendor_id'} );
1249 $client{'vendor-guid'} = $vendorGuid;
1250 }
1251 $client{'country'} = CommonPacker::normalizeCountry( $client{'country'} );
1252
1253 my %passwd;
1254 unless ( $self->{shallow_dump} ) {
1255 $sql = "SELECT password, type FROM accounts WHERE id = ?";
1256
1257 if ( $self->{dbh}->execute($sql, $client{'account_id'}) ) {
1258 if ( $ptrHash = $self->{dbh}->fetchhash() ) {
1259 %passwd = (
1260 'password' => $ptrHash->{'password'},
1261 'type' => CommonPacker::normalizePasswordType( $ptrHash->{'type'} )
1262 );
1263 }
1264 else {
1265 %passwd = ( 'password' => '', 'type' => 'plain' );
1266 my $msg = "Broken referencial integrity: Account password is not found for client " . $client{'account_id'};
1267 print STDERR "$msg\n";
1268 Logging::warning( $msg , 'BrokenDbIntegrity');
1269 }
1270 }
1271 $self->{dbh}->finish();
1272 }
1273 my $status = $client{'status'};
1274
1275 my $doNotDumpDomainTemplates = 0;
1276
1277 my $parentType;
1278
1279 if( $parent ) {
1280 $parentType = PleskStructure::getClientType( $parent );
1281 $client{'owner-guid'} = PleskStructure::getClientGuid( $parent );
1282 $client{'owner-name'} = $parent;
1283 } else{
1284 $parentType = 'admin';
1285 $client{'owner-guid'} = PleskStructure::getAdminGuid();
1286 $client{'owner-name'} = 'admin';
1287 }
1288
1289 if( $clientType eq 'client' ){
1290
1291 if ( exists $client{'vendor_id'} ){
1292 my $vendorLogin = PleskStructure::getClientNameFromId( $client{'vendor_id'} );
1293 $client{'vendor-login'} = $vendorLogin;
1294 }
1295
1296 if( $isroot ){
1297 if ($self->{admin_info} or $self->{server_settings}) {
1298 $self->{packer}->addAdminClient( $clientId, \%client, \%passwd, $status );
1299 } else {
1300 $self->{packer}->addRootClient( $clientId, \%client, \%passwd, $status );
1301 }
1302 }
1303 else{
1304
1305 if( $parentType eq 'admin' ) {
1306 $self->{packer}->addAdminClient( $clientId, \%client, \%passwd, $status );
1307 }
1308 elsif( $parentType eq 'reseller' ) {
1309 $doNotDumpDomainTemplates = 1;
1310 $self->{packer}->addResellerClient($client{'parent_id'}, $clientId, \%client, \%passwd, $status );
1311 }
1312 else{
1313 die "Cannot dump client '$clientName' of type '$clientType', parent '$parent' type '$parentType' not supported!";
1314 }
1315 }
1316 }
1317
1318 elsif( $clientType eq 'reseller' ){
1319
1320 if( $isroot ){
1321 if ( $self->{admin_info} or $self->{server_settings} ) {
1322 $self->{packer}->addAdminReseller( $clientId, \%client, \%passwd, $status );
1323 } else {
1324 $self->{packer}->addRootReseller( $clientId, \%client, \%passwd, $status );
1325 }
1326 }
1327 else{
1328
1329 if( $parentType eq 'admin' ) {
1330 $self->{packer}->addAdminReseller( $clientId, \%client, \%passwd, $status );
1331 }
1332 else{
1333 die "Cannot dump client '$clientName' of type '$clientType', parent '$parent' type '$parentType' not supported!";
1334 }
1335
1336 }
1337 }
1338
1339 else{
1340 die "Cannot dump client '$clientName'. unknown type '$clientType'!";
1341 }
1342
1343 $sql = "SELECT param,val FROM cl_param WHERE cl_id = ?";
1344 if ( $self->{dbh}->execute_rownum($sql, $clientId) ) {
1345 while ( $ptrRow = $self->{dbh}->fetchrow() ) {
1346 $clientParams{ $ptrRow->[0] } = $ptrRow->[1];
1347 }
1348 }
1349 $self->{dbh}->finish();
1350
1351 unless ( $self->{shallow_dump} ) {
1352
1353 $self->{packer}->setClientPinfo( $clientId, \%client );
1354
1355 if ( exists( $client{'locale'} ) && $client{'locale'} ) {
1356 $self->{packer}->setClientLocale( $clientId, $client{'locale'} );
1357 }
1358
1359 if ( ($clientType eq 'reseller')
1360 or (DAL::isBusinessModelUpgraded() and ($client{'limits_id'} or $client{'perm_id'})) )
1361 {
1362 #
1363 # limits
1364 #
1365
1366 if( $clientType eq 'reseller' ) {
1367 $self->addResellerLimits( $clientId, $client{'limits_id'} );
1368 }
1369 else{
1370 $self->addClientLimits( $clientId, $client{'limits_id'} );
1371 }
1372
1373 $self->addClientOverusePolicy( $clientId, \%clientParams );
1374 $self->{packer}->fixDefaultLimits($clientType,$clientId);
1375
1376 #
1377 # end limits
1378 #
1379
1380 $self->addPermissions( $clientId, 'client', $client{'perm_id'} );
1381
1382 #fix bug 88139
1383 if ( !$client{'perm_id'} )
1384 {
1385 $self->{packer}->addClientPermission( $clientId, 'cp_access', 'true' );
1386 }
1387
1388 $self->addClientMulitpleLoginPermission($clientId, $clientParams{'multiply_login'} ) if exists $clientParams{'multiply_login'};
1389 }
1390
1391 #
1392 # Domain skeleton
1393 #
1394
1395 my $skeletonPath =
1396 AgentConfig::get('HTTPD_VHOSTS_D') . "/.skel/$clientId";
1397
1398 if ( !$self->{configuration_dump} && !$self->{only_mail_dump} ) {
1399 $self->{packer}->addClientDomainSkeleton( $clientId, $skeletonPath, "skel" );
1400 }
1401 }
1402
1403 my %ips = PleskStructure::getClientIps($clientName);
1404
1405 $self->{packer}->addClientIps( $clientId, \%ips );
1406
1407 $self->addClientTraffic($clientId);
1408
1409 unless ($doNotDumpDomainTemplates) {
1410 $self->dumpDomainTemplates( $clientId, $clientType );
1411 }
1412
1413 if( $childClients and @{$childClients} and @{$domains} ) {
1414 # we are in reseller node and should add nodes <domains> and <clients> before processing of domains, as this could lead to creating users and roles
1415 $self->{packer}->addResellerDomainsClientsNodes( $clientId );
1416 }
1417
1418 # Make childs dump
1419 if( $childClients ){
1420 foreach my $myClientName( @{$childClients} ) {
1421 #TO DO check excluded clients. Not worked now
1422 my @clientdomains = PleskStructure::getDomainsForClient( $myClientName );
1423 @clientdomains = sort { $a cmp $b } @clientdomains;
1424 @clientdomains = $self->{filter}->filterSelectedDomains( \@clientdomains );
1425 eval {
1426 $self->makeClientNode($myClientName, \@clientdomains, undef, 0 );
1427 1;
1428 } or do {
1429 $self->checkProgramTerminated();
1430 $self->excludeProblemClientFromBackup( $myClientName, $@ );
1431 }
1432 }
1433 $self->{packer}->removeResellerChildNodeIfEmpty( $clientId, 'clients' );
1434 }
1435
1436 for my $domainName ( @{$domains} ) {
1437 eval {
1438 $self->makeDomainNode( $domainName, 0 );
1439 1;
1440 } or do {
1441 $self->checkProgramTerminated();
1442 $self->excludeProblemDomainFromBackup( $domainName, $@ );
1443 };
1444 }
1445 $self->{packer}->removeResellerChildNodeIfEmpty( $clientId, 'domains' );
1446
1447 my @users = PleskStructure::getUserLogins($clientName);
1448
1449 my $callback = sub {
1450 $self->{packer}->addClientUser( $clientId, @_ );
1451 };
1452
1453 my $callbackFailed = sub {
1454 $self->{packer}->removeClientUser( $clientId, @_ );
1455 };
1456
1457 my $callbackRole = sub {
1458 $self->{packer}->removeClientRole( $clientId, @_ );
1459 };
1460
1461 $self->addUsers( \@users, $callback, $callbackFailed );
1462
1463 for my $roleId (PleskStructure::getRoleIds($clientName) ) {
1464 my @role = grep {$_->{'id'}==$roleId and $_->{'isBuiltIn'}==0} @{DAL::selectSmbRoles()};
1465 eval {
1466 if ( @role ) {
1467 $self->{packer}->addClientRole($clientId, $role[0]->{'name'}, 0, $self->getRolePermissions($roleId), DAL::getRoleServicePermissions($roleId));
1468 }
1469 1;
1470 } or do {
1471 $self->excludeProblemRoleFromBackup( $callbackRole, $role[0]->{'name'}, $@ );
1472 }
1473 }
1474
1475 $self->getCustomButtonsByOwner( $clientType, $clientId );
1476
1477 $self->getSubscription('client', $clientId);
1478
1479 if (exists $clientParams{'theme_skin'} and not $self->{configuration_dump}) {
1480 if ( $clientType eq 'reseller' ) {
1481 $self->{packer}->makeSkinNode($clientParams{'theme_skin'}, $clientName, $clientId);
1482 }
1483 }
1484
1485 $self->dumpApsBundle($clientId, 'client');
1486
1487 if ( $clientType eq 'reseller' ) {
1488 my $clientsDescriptions = DAL::getClientsDescriptions( $clientId );
1489 my $subscriptionsDescriptions = DAL::getSubscriptionsResellerDescriptions( $clientId );
1490 my @allDescriptions = ( @{$clientsDescriptions}, @{$subscriptionsDescriptions} );
1491 $self->{packer}->makeResellerDescriptionsNode( $clientId, \@allDescriptions );
1492 }
1493
1494 $self->{packer}->makeClParamNode( $clientId, $clientType, \%clientParams );
1495
1496 $self->{packer}->makeExtensionNode($clientType, $clientId);
1497
1498 $self->{packer}->finishClient($clientId);
1499 $self->{dump_status}->endClient($clientName);
1500
1501 Logging::endObject();
1502}
1503
1504sub addDomainOverusePolicy{
1505 my( $self, $parentId, $params ) = @_;
1506
1507 if( exists $params->{'DecompositionRule'} ){
1508 my $oversell = ($params->{'DecompositionRule'} eq 'oversell')? 'true' : 'false';
1509 $self->{packer}->addDomainLimit( $parentId, 'oversell', $oversell );
1510 }
1511
1512 my $overuse = 'normal';
1513 if( exists $params->{'OveruseBlock'} ){
1514 if( $params->{'OveruseBlock'} eq 'true' ){
1515 if ( exists $params->{'OveruseSuspend'}) {
1516 if ( $params->{'OveruseSuspend'} eq 'true') {
1517 $overuse = 'block';
1518 }
1519 else {
1520 if ( $params->{'OveruseNotify'} eq 'true') {
1521 $overuse = 'not_suspend_notify';
1522 } else {
1523 $overuse = 'not_suspend';
1524 }
1525 }
1526 }
1527 else {
1528 $overuse = 'not_suspend';
1529 }
1530 }
1531 else {
1532 if( $params->{'OveruseNotify'} eq 'true' ){
1533 $overuse = 'notify';
1534 }
1535 else {
1536 $overuse = 'normal';
1537 }
1538 }
1539 }
1540 $self->{packer}->addDomainLimit( $parentId, 'overuse', $overuse );
1541}
1542
1543sub addClientOverusePolicy{
1544 my( $self, $parentId, $params ) = @_;
1545
1546 if( exists $params->{'DecompositionRule'} ){
1547 my $oversell = ($params->{'DecompositionRule'} eq 'oversell')? 'true' : 'false';
1548 $self->{packer}->addClientLimit( $parentId, 'oversell', $oversell );
1549 }
1550
1551 my $overuse;
1552 if( $params->{'OveruseBlock'} eq 'true' ){
1553 $overuse = 'block';
1554 }
1555 elsif( $params->{'OveruseNotify'} eq 'true' ){
1556 $overuse = 'notify';
1557 }
1558 else {
1559 $overuse = 'normal';
1560 }
1561
1562 $self->{packer}->addClientLimit( $parentId, 'overuse', $overuse );
1563}
1564
1565sub addPermissions {
1566 my ( $self, $parent, $parentType, $id ) = @_;
1567
1568 unless($parentType eq 'client' || $parentType eq 'domain-personal') {
1569 Logging::warning( "Error: addPermissions: Unexpected type of parent \"$parentType\"",'assert');
1570 return;
1571 }
1572
1573 my $permsHash = $self->getPermsHash($id);
1574 return unless $permsHash;
1575
1576 foreach my $key ( keys %{$permsHash} ) {
1577 if ( $parentType eq 'client' ) {
1578 $self->{packer}->addClientPermission( $parent, $key, $permsHash->{$key} );
1579 }
1580 else {
1581 $self->{packer}->addDomainPersonalPermission( $parent, $key, $permsHash->{$key} );
1582 }
1583 }
1584}
1585
1586sub getPermsHash {
1587 my ( $self, $permsId ) = @_;
1588
1589 return unless $permsId;
1590
1591 my $sql = "SELECT permission,value FROM Permissions WHERE id=?";
1592
1593 my %permsHash;
1594 if ( $self->{dbh}->execute_rownum($sql, $permsId) ) {
1595 while ( my $ptrRow = $self->{dbh}->fetchrow() ) {
1596 my $name = $ptrRow->[0];
1597 my $value = HelpFuncs::convertToTrueFalseString($ptrRow->[1]);
1598 $name = "manage_virusfilter" if $name eq "manage_drweb";
1599 $name = "manage_php_settings" if $name eq "manage_php_safe_mode";
1600
1601 if ( $name eq 'make_dumps' ) {
1602 $permsHash{'allow_local_backups'} = $value;
1603 $permsHash{'allow_ftp_backups'} = $value;
1604 $permsHash{'allow_account_local_backups'} = $value;
1605 $permsHash{'allow_account_ftp_backups'} = $value;
1606 next;
1607 }
1608
1609 $permsHash{$name} = $value;
1610 }
1611 }
1612 $self->{dbh}->finish();
1613
1614 $sql = "SELECT value FROM Permissions WHERE id = ? and ("
1615 . "permission = 'ipb_allow' or permission = 'nb_allow')";
1616 if ( $self->{dbh}->execute_rownum($sql, $permsId) ) {
1617 if ( my $ptrRow = $self->{dbh}->fetchrow() ) {
1618 my $value = HelpFuncs::convertToTrueFalseString(@{ $ptrRow }[0]);
1619 $permsHash{'manage_phosting'} = $value;
1620 }
1621 }
1622 $self->{dbh}->finish();
1623
1624 return \%permsHash;
1625}
1626
1627sub addClientMulitpleLoginPermission {
1628 my ( $self, $id, $multiple_sessions ) = @_;
1629 $self->{packer}->addClientPermission( $id, 'multiple-sessions', $multiple_sessions );
1630}
1631
1632sub insertLimit {
1633 my ( $self, $parent, $parentType, $name, $value ) = @_;
1634
1635 if ( (!defined $value) || ($value eq '') ) {
1636 $value = '-1';
1637 }
1638 if( $value ne '-1') {
1639 if ( $name eq 'expiration' ) {
1640 my ( $mday, $mon, $year ) = ( localtime($value) )[ 3 .. 5 ];
1641 $mon++;
1642 $year += 1900;
1643 $value = sprintf( '%04d-%02d-%02d', $year, $mon, $mday );
1644 }
1645 }
1646
1647 if ( $parentType eq 'client' || $parentType eq 'reseller' ) {
1648 $self->{packer}->addClientLimit( $parent, $name, $value );
1649 }
1650 elsif ( $parentType eq 'domain' ) {
1651 $self->{packer}->addDomainLimit( $parent, $name, $value );
1652 }
1653 else {
1654 Logging::warning( "Error: insertLimits: Unexpected type of parent \"$parentType\"",'assert');
1655 }
1656}
1657
1658sub addResellerLimits {
1659 my ( $self, $resellerId, $limitsId ) = @_;
1660 return $self->addLimits( $resellerId, 'reseller', $limitsId);
1661}
1662
1663sub addClientLimits {
1664 my ( $self, $clientId, $limitsId ) = @_;
1665 return $self->addLimits( $clientId, 'client', $limitsId);
1666}
1667
1668sub addDomainLimits {
1669 my ( $self, $domainId, $limitsId ) = @_;
1670 return $self->addLimits( $domainId, 'domain', $limitsId);
1671}
1672
1673sub addLimits {
1674 my ( $self, $parent, $parentType, $limitId) = @_;
1675
1676 my $count = 0;
1677
1678 my ( $sql, $ptrRow, $value, $name );
1679 $sql = "SELECT limit_name,value FROM Limits WHERE id=?";
1680 if ( $self->{dbh}->execute_rownum($sql, $limitId) ) {
1681 $count = 0;
1682 while ( $ptrRow = $self->{dbh}->fetchrow() ) {
1683 ( $name, $value ) = @{$ptrRow};
1684 $self->insertLimit( $parent, $parentType, $name, $value );
1685 $count++;
1686 }
1687 }
1688 $self->{dbh}->finish();
1689 return $count;
1690}
1691
1692sub dumpDomainTemplates {
1693 my ( $self, $clientId, $clientType ) = @_;
1694
1695 $self->dumpTemplates( $clientId, $clientType, 'domain' );
1696 $self->dumpTemplates( $clientId, $clientType, 'domain_addon' );
1697}
1698
1699sub dumpTemplates {
1700 my ( $self, $parent, $parentType, $templateType ) = @_;
1701 return $self->dumpTemplates9x($parent, $parentType, undef, $templateType);
1702}
1703
1704# explicit function for dumping single plan to avoid legacy suffix 9x
1705sub dumpTemplate {
1706 my ( $self, $parent, $parentType, $template, $templateType ) = @_;
1707 return $self->dumpTemplates9x($parent, $parentType, $template, $templateType);
1708}
1709
1710my %dumped_templates;
1711sub dumpTemplates9x {
1712 my ( $self, $parent, $parentType, $tmpl_id, $templateType ) = @_;
1713
1714 my $sql;
1715
1716 my $ownerGuid;
1717
1718 my %templateNames;
1719 my %templateUuids;
1720 my %templateExtIds;
1721
1722 $ownerGuid = PleskStructure::getClientGuidFromId($parent);
1723
1724 $sql = "SELECT * FROM Templates WHERE ";
1725 my @sqlParams = ();
1726 if ($tmpl_id) {
1727 $sql .= "id = ?";
1728 push(@sqlParams, $tmpl_id);
1729 } else {
1730 $sql .= "owner_id = ? AND type = '?'";
1731 push(@sqlParams, $parent, $templateType);
1732 }
1733
1734 if ( $self->{dbh}->execute($sql, @sqlParams) ) {
1735 while ( my $ptrHash = $self->{dbh}->fetchhash() ) {
1736 my $id = $ptrHash->{'id'};
1737 if (not exists $dumped_templates{$id}) {
1738 $dumped_templates{$id} = 1;
1739 $templateNames{ $id } = $ptrHash->{'name'};
1740 $templateUuids{ $id } = $ptrHash->{'uuid'};
1741 $templateExtIds{ $id } = $ptrHash->{'external_id'} if defined $ptrHash->{'external_id'} and $ptrHash->{'external_id'} ne '';
1742 }
1743 }
1744 }
1745 $self->{dbh}->finish();
1746
1747 my @planItemNames = @{$self->getPlanItemNames()};
1748
1749 while ( my ( $template_id, $tmpl_name ) = each %templateNames ) {
1750
1751 my @template;
1752
1753 my $logrotation_id;
1754 my $ip_pool_id;
1755 my $overuse_block;
1756 my $overuse_notify;
1757 my $overuse_suspend;
1758 my $aps_bundle_filter_id = undef;
1759 my %phpSettings;
1760 my %phpHandlerSettings = ('php_handler_id' => undef, 'php_handler_type' => undef, 'php_version' => undef);
1761 my @defaultDbServers;
1762 my %webServerSettings;
1763 my %planItems;
1764
1765 if ( $self->{dbh}->execute("SELECT element, value FROM TmplData WHERE tmpl_id=?", $template_id) ) {
1766 my @tmplData;
1767 while ( my $ptrRow = $self->{dbh}->fetchrow() ) {
1768 my @tmplElem = @{$ptrRow};
1769 push @tmplData, \@tmplElem;
1770 }
1771
1772 foreach my $ptrRow (@tmplData) {
1773 my ( $element, $value ) = @{$ptrRow};
1774
1775 if ( !defined($value) ) {
1776 $value = '';
1777 }
1778
1779 if ( $element eq 'stat_ttl' and ( $value == 0 or $value eq '' ) ) {
1780 $value = -1;
1781 }
1782
1783 if ( $element eq 'logrotation_id' ) {
1784 $logrotation_id = $value;
1785 next;
1786 }
1787
1788 if ($element eq 'tmpl_pool_id') {
1789 $ip_pool_id = $value;
1790 next;
1791 }
1792
1793 if( $element eq 'overuse_block' ){
1794 $overuse_block = $value;
1795 next;
1796 }
1797
1798 if( $element eq 'overuse_notify' ){
1799 $overuse_notify = $value;
1800 next;
1801 }
1802
1803 if ( $element eq 'overuse_suspend' ){
1804 $overuse_suspend = $value;
1805 next;
1806 }
1807
1808 if ( grep $_ eq $element, @planItemNames) {
1809 $planItems{ $element } = $value;
1810 next;
1811 }
1812 if ($element eq 'aps_bundle_filter_id') {
1813 $aps_bundle_filter_id = $value;
1814 }
1815
1816 if ($element eq 'phpSettingsId') {
1817 %phpSettings = %{DAL::getPhpSettings($value)};
1818 my $phpSettingsCustom = DAL::getPhpSettingsCustom($value);
1819 $phpSettings{'notice'} = $phpSettingsCustom if defined $phpSettingsCustom;
1820 }
1821
1822 if ($element eq 'default_server_mysql'
1823 or $element eq 'default_server_postgresql'
1824 ) {
1825 foreach my $ptrHash (@{DAL::getDatabaseServers()}) {
1826 if ($value == $ptrHash->{'id'}) {
1827 push @defaultDbServers, $ptrHash;
1828 }
1829 }
1830 }
1831
1832 if ($element eq 'webServerSettingsId') {
1833 my $webServerSettings = DAL::getWebServerSettings($value);
1834 while (my ($settingName, $settingValue) = each(%{$webServerSettings})) {
1835 my @data = ( $settingName, $self->{packer}->{base64}->{'ENCODE'}->($settingValue) );
1836 push @template, \@data;
1837 };
1838 }
1839
1840 if ( 'domain_addon' eq $templateType ) {
1841 # skip items which are not allowed for domain_addon template
1842 my %template_items_ignore_addon = (
1843 'cp_access' => 1,
1844 'remote_access_interface' => 1,
1845 'disk_space_soft' => 1,
1846 'max_traffic_soft' => 1,
1847 'stat_ttl' => 1,
1848 'maillists' => 1,
1849 'overuse' => 1,
1850 'dns_type' => 1,
1851 'nonexist_mail' => 1
1852 );
1853 next if exists $template_items_ignore_addon{$element};
1854 }
1855 if ( 'domain' eq $templateType ) {
1856 # skip items which are not allowed for domain template
1857 next if ($element eq 'cp_access' or $element eq 'remote_access_interface');
1858 }
1859
1860 if ( $element eq 'quota' and ( $value eq 'false' or $value == 0 ) ) {
1861 $value = -1;
1862 }
1863
1864 my %emptyableBoolElementInTemplate = (
1865 'asp' => 1,
1866 'cgi' => 1,
1867 'pdir_plesk_stat' => 1,
1868 'perl' => 1,
1869 'php' => 1,
1870 'python' => 1,
1871 'ssi' => 1
1872 );
1873 if ( $value eq '' and exists $emptyableBoolElementInTemplate{$element} ) {
1874 $value = 'false';
1875 }
1876
1877 if (exists($phpHandlerSettings{$element})) {
1878 $phpHandlerSettings{$element} = $value;
1879 next;
1880 }
1881
1882 my @data = ( $element, $value );
1883 push @template, \@data;
1884 }
1885 }
1886 $self->{dbh}->finish();
1887
1888 my $logRotation = {};
1889 if ( $logrotation_id and ( $templateType eq 'domain' ) ) {
1890 $logRotation = DAL::getLogrotation($logrotation_id);
1891 }
1892
1893 my %ipPool;
1894 if ( $ip_pool_id and ( $templateType eq 'reseller' or $templateType eq 'client' ) ) {
1895 %ipPool = $self->makeTemplateIpPool($ip_pool_id);
1896 }
1897
1898 if( $overuse_block and ('domain_addon' ne $templateType )){
1899 my @data = ( 'overuse' );
1900 if( $overuse_block eq 'true' ) {
1901 if ( $overuse_suspend ) {
1902 if ($overuse_suspend eq 'true') {
1903 push @data, 'block';
1904 } else {
1905 if ($overuse_notify eq 'true') {
1906 push @data, 'not_suspend_notify';
1907 } else {
1908 push @data, 'not_suspend';
1909 }
1910 }
1911 } else {
1912 push @data, 'block';
1913 }
1914 }
1915 elsif( $overuse_notify and $overuse_notify eq 'true' ) { push @data, 'notify'; }
1916 else{ push @data, 'normal'; }
1917 push @template, \@data;
1918 }
1919
1920 if ($phpHandlerSettings{'php_handler_id'}) {
1921 my $phpHandlerId = $phpHandlerSettings{'php_handler_id'};
1922 push(@template, ['php_handler_id', $phpHandlerId]);
1923 my $phpHandlers = HostingDumper::getPhpHandlers();
1924 if (exists($phpHandlers->{$phpHandlerId})) {
1925 push(@template, ['php_handler_type', $phpHandlers->{$phpHandlerId}{'type'}]);
1926 push(@template, ['php_version', $phpHandlers->{$phpHandlerId}{'version'}]);
1927 }
1928 } else {
1929 push(@template, ['php_handler_type', $phpHandlerSettings{'php_handler_type'}]) if $phpHandlerSettings{'php_handler_type'};
1930 push(@template, ['php_version', $phpHandlerSettings{'php_version'}]) if $phpHandlerSettings{'php_version'};
1931 }
1932
1933 my @templateAttrs;
1934
1935 if ( defined $templateUuids{$template_id} ) {
1936 my @guidAttr = ( 'guid', $templateUuids{$template_id});
1937 push @templateAttrs, \@guidAttr;
1938 }
1939
1940 if ( defined $templateExtIds{$template_id} ) {
1941 my @extIdAttr = ( 'external-id', $templateExtIds{$template_id});
1942 push @templateAttrs, \@extIdAttr;
1943 }
1944
1945 if ( defined $ownerGuid ) {
1946 my @ownerGuidAttr = ( 'owner-guid', $ownerGuid);
1947 push @templateAttrs, \@ownerGuidAttr;
1948 }
1949
1950 if ( $templateType eq 'domain_addon') {
1951 my @isAddonAttr = ( 'is-addon', 'true');
1952 push @templateAttrs, \@isAddonAttr;
1953 }
1954
1955 my @apsFilterItems;
1956 my $filterType;
1957 if (defined($aps_bundle_filter_id)) {
1958 @apsFilterItems = @{DAL::getApsBundleFilterItems($aps_bundle_filter_id)};
1959 $filterType = DAL::getApsBundleFilterType($aps_bundle_filter_id);
1960 }
1961
1962 my %packerData;
1963 $packerData{'attributes'} = \@templateAttrs;
1964 $packerData{'data'} = \@template;
1965 $packerData{'items'} = \%planItems;
1966 $packerData{'log-rotation'} = $logRotation;
1967 $packerData{'ip-pool'} = \%ipPool;
1968 $packerData{'aps-filter-items'} = \@apsFilterItems;
1969 $packerData{'aps-filter-type'} = $filterType;
1970 $packerData{'php-settings'} = \%phpSettings;
1971 $packerData{'default-db-servers'} = \@defaultDbServers;
1972
1973 if ( $parentType eq 'server' ) {
1974 $self->{packer}->addTemplateToServer($templateType, $tmpl_name, \%packerData);
1975 }
1976 elsif ( $parentType eq 'reseller' ) {
1977 if ( 'domain' eq $templateType or 'domain_addon' eq $templateType) {
1978 $self->{packer}->addResellerDomainTemplate( $parent, $tmpl_name, \%packerData);
1979 }
1980 else {
1981 Logging::warning("Error: dumpTemplates: unexpected template type \"$templateType\" for parent \"$parentType\"",'assert');
1982 }
1983 }
1984 elsif ( $parentType eq 'client' ) {
1985 if ( 'domain' eq $templateType or 'domain_addon' eq $templateType) {
1986 $self->{packer}->addClientDomainTemplate( $parent, $tmpl_name, \%packerData);
1987 }
1988 else {
1989 Logging::warning("Error: dumpTemplates: unexpected template type \"$templateType\" for parent \"$parentType\"",'assert');
1990 }
1991 }
1992 else {
1993 Logging::warning("Error: dumpTemplates: Unexpected type of parent \"$parentType\"",'assert');
1994 }
1995 }
1996}
1997
1998sub makeTemplateIpPool {
1999 my ( $self, $ip_pool_id ) = @_;
2000
2001 my $sql = "SELECT IP_Addresses.`ip_address`, ip_pool.`type`" .
2002 " FROM ip_pool".
2003 " LEFT JOIN IP_Addresses ON ip_pool.`ip_address_id` = IP_Addresses.`id`" .
2004 " WHERE ip_pool.`id` = ?";
2005
2006 my %ipPool = ();
2007
2008 if ( $self->{dbh}->execute_rownum($sql, $ip_pool_id) ) {
2009 while ( my $ptrRow = $self->{dbh}->fetchrow() ) {
2010 $ipPool{ $ptrRow->[0] } = $ptrRow->[1];
2011 }
2012 }
2013 $self->{dbh}->finish();
2014
2015 return %ipPool;
2016}
2017
2018sub makeDomainNode {
2019 my ( $self, $domainName, $isroot ) = @_;
2020
2021 $self->checkProgramTerminated();
2022
2023 $self->{isAnyDbDumpedOnDomain} = 0;
2024
2025 if( $self->domainExcluded( $domainName ) ) {
2026 Logging::debug("Domain '$domainName' is excluded from dump");
2027 return;
2028 }
2029
2030 foreach my $dumpedDomain( @{$self->{dumped_domains}} ){
2031 if( $dumpedDomain eq $domainName ){
2032 Logging::debug("Domain '$domainName' already dumped");
2033 return;
2034 }
2035 }
2036 push @{$self->{dumped_domains}}, $domainName;
2037
2038 Logging::debug("Domain '$domainName' is started");
2039 Logging::beginObject('domain',$domainName, $self->generateObjectUuidForLogging('domain', $domainName));
2040
2041 $self->{dump_status}->startDomain($domainName);
2042
2043 my ( $sql, $ptrHash );
2044
2045 Logging::debug("Getting domain info");
2046 my $domainPtr;
2047 $domainPtr = DAL::getDomainPtr($domainName);
2048
2049 unless( $domainPtr ) {
2050 Logging::error("Failed to get domain hash for '$domainName'",'PleskDbError');
2051 Logging::endObject();
2052 return;
2053 }
2054 my %domain = %{$domainPtr};
2055
2056 # There are no guid field in 'domains' table in the old Plesk, but currently it is a required parameter, so we set empty guid here and it will be replaced with non-empty value by resolver
2057 $domain{'guid'} = '' if !defined $domain{'guid'};
2058
2059 my $domainId = $domain{'id'};
2060 my $clientId = $domain{'cl_id'};
2061
2062 $self->_initDomainContentStat($domainId);
2063
2064 my $embeddedInfo = DAL::getEmbeddedInfo(['--backup-subscription', $domain{'name'}]);
2065
2066 if ( exists $domain{'vendor_id'} ){
2067 my $vendorGuid = PleskStructure::getClientGuidFromId( $domain{'vendor_id'} );
2068 $domain{'vendor-guid'} = $vendorGuid;
2069 my $vendorLogin = PleskStructure::getClientNameFromId( $domain{'vendor_id'} );
2070 $domain{'vendor-login'} = $vendorLogin;
2071 }
2072
2073 if ( defined PleskStructure::getClientGuidFromId($clientId) ) {
2074 $domain{'owner-guid'} = PleskStructure::getClientGuidFromId($clientId);
2075 $domain{'owner-name'} = PleskStructure::getClientNameFromId($clientId);
2076 }
2077
2078 my $clientPermsId;
2079 $sql = "SELECT perm_id FROM clients WHERE id = ?";
2080
2081 if ( $self->{dbh}->execute_rownum($sql, $clientId) and my $ptrRow = $self->{dbh}->fetchrow() ) {
2082 $clientPermsId = $ptrRow->[0];
2083 }
2084 $self->{dbh}->finish();
2085
2086 my $domainAsciiName;
2087 $domainName = $domain{'displayName'};
2088 $domainAsciiName = $domain{'name'};
2089
2090 my $domainOwner = PleskStructure::getClientNameFromId( $domain{'cl_id'} );
2091 my $parentType = PleskStructure::getClientType( $domainOwner );
2092 if( $isroot ){
2093 if ($self->{admin_info} or $self->{server_settings}) {
2094 $self->{packer}->addAdminDomain( $domainId, $domainName, $domainAsciiName, \%domain );
2095 } else {
2096 $self->{packer}->addRootDomain( $domainId, $domainName, $domainAsciiName, \%domain, PleskStructure::getClientGuid($domainOwner) );
2097 }
2098 }
2099 else{
2100 if( $parentType eq 'admin' ){
2101 $self->{packer}->addAdminDomain( $domainId, $domainName, $domainAsciiName, \%domain );
2102 }
2103 elsif( $parentType eq 'reseller' ){
2104 $self->{packer}->addResellerDomain( $domain{'cl_id'}, $domainId, $domainName, $domainAsciiName, \%domain );
2105 }
2106 elsif( $parentType eq 'client' ){
2107 $self->{packer}->addClientDomain( $domain{'cl_id'}, $domainId, $domainName, $domainAsciiName, \%domain );
2108 }
2109 else{
2110 die "Cannot dump domain '$domainName'. Domain owner '$domainOwner' type '$parentType' is not supported!";
2111 }
2112 }
2113
2114 $self->{suspender}->suspendDomain( $domainName );
2115
2116 $domainAsciiName = $domain{'name'};
2117 my $domainType = $domain{'htype'};
2118
2119 $self->addWwwStatus( $domainId, $domainAsciiName );
2120
2121 # Domain's IP address
2122 Logging::debug("Getting domain IP");
2123 my $ip = PleskStructure::getDomainIp($domainName);
2124 if ($ip) {
2125 foreach my $ipAddress (@{$ip}) {
2126 $self->{packer}->setDomainIP( $domainId, $ipAddress, PleskStructure::getClientIpType( $domainOwner, $ipAddress ) );
2127 }
2128 }
2129
2130 #
2131 # Status
2132 #
2133 Logging::debug("Dumping domain status");
2134
2135 my $status = 0;
2136 my $siteStatus = undef;
2137
2138 $status = $domain{'status'};
2139 $status += 0;
2140 $status = $domain{'webspace_status'};
2141 $siteStatus = $domain{'status'};
2142
2143 $self->{packer}->setWebspaceStatus( $domainId, $status, $siteStatus );
2144
2145 #
2146 # No further info required if shallow dump specified
2147 #
2148 if ( $self->{shallow_dump} && !$self->{only_mail_dump} ) {
2149
2150 # Need to dump information about all databases for DbServers mapping
2151
2152 Logging::debug("Dumping domain databases");
2153 foreach my $db (@{DAL::getDomainDatabases($domainId)}) {
2154 eval {
2155 $self->makeDatabaseNode( $db->{'id'}, $domainId, 'domain', undef, undef, $embeddedInfo );
2156 1;
2157 } or do {
2158 $self->checkProgramTerminated();
2159 $self->excludeProblemDatabaseFromBackup( $domainId, $db, $@ );
2160 }
2161 }
2162
2163 eval {
2164 # Domain's DNS settings
2165 $self->makeDomainDnsZone( \%domain );
2166
2167 if ((!defined $ip) && ( $domainType ne 'vrt_hst' ) ) {
2168 my $preferredIp = $self->{packer}->getDomainARecordIp($domainId);
2169 my $type;
2170 $ip = PleskStructure::getIp4DomainWoHosting($domainId, $preferredIp, \$type);
2171 if ( $ip ) {
2172 foreach my $ipAddress (@{$ip}) {
2173 $self->{packer}->setDomainIP( $domainId, $ipAddress, $type );
2174 }
2175 } else {
2176 my $serviceIps = $self->getServiceIps( $domainId, 'mail', $ip );
2177 if ($serviceIps) {
2178 foreach my $serviceIp (keys %{$serviceIps}) {
2179 $self->{packer}->setDomainIP( $domainId, $serviceIp, $serviceIps->{$serviceIp} );
2180 last;
2181 }
2182 }
2183 }
2184 }
2185 1;
2186 } or do {
2187 $self->excludeProblemDnsZoneFromBackup( $domainId, $@ );
2188 };
2189
2190 $self->{packer}->removeDomainDnsZone($domainId);
2191
2192 $self->{suspender}->unSuspendDomain();
2193
2194 $self->{packer}->finishDomain($domainId);
2195 $self->{dump_status}->endDomain($domainName);
2196 Logging::endObject();
2197 $self->{packer}->{stat}{dbDumpsCount}++ if ($self->{isAnyDbDumpedOnDomain} == 1);
2198 return;
2199 }
2200
2201 # Check whether this domain is default on IP
2202
2203 $sql = "SELECT COUNT(*) FROM IP_Addresses WHERE default_domain_id=?";
2204 if ( $self->{dbh}->execute_rownum($sql, $domainId) ) {
2205 if ( @{ $self->{dbh}->fetchrow() }[0] ne "0" ) {
2206 $self->{packer}->setDomainDefault($domainId);
2207 }
2208 }
2209 $self->{dbh}->finish();
2210
2211 if ( !$self->{only_mail_dump} ) {
2212 # Domain's aliases
2213 $self->dumpDomainAliases($domainId);
2214 }
2215
2216 my $domParams = $self->getDomainParams(\%domain);
2217
2218 Logging::debug("Getting domain limits and permissions");
2219
2220 if ( !$self->{only_mail_dump} ) {
2221 my $subscriptionProperties = DAL::getDomainSuscriptionProperties($domainId);
2222 $self->addDomainLimits( $domainId, $subscriptionProperties->{'limitsId'} );
2223 $self->addDomainOverusePolicy( $domainId, $subscriptionProperties );
2224 # The following call of fixDefaultLimits should be before permissions dumping to avoid validation by schema fails
2225 $self->{packer}->fixDefaultLimits('domain',$domainId);
2226 $self->dumpDomainPersonalPermissions( $domainId, $subscriptionProperties->{'permissionsId'} );
2227 }
2228
2229 if ( !$self->{only_hosting_dump} ) {
2230 eval {
2231 $self->dumpMailSystem( $parentType, $domParams, \%domain, $isroot, $ip );
2232 1;
2233 } or do {
2234 $self->checkProgramTerminated();
2235 $self->excludeProblemMailSystemFromBackup( $domainId, $@ );
2236 }
2237 } else {
2238 Logging::debug("Skip domain mailsystem dump due to settings");
2239 }
2240
2241 my @SiteApplications;
2242 my @excluded_dbs;
2243 my @excluded_dns_records;
2244 my $applicationsInstalled = 1;
2245
2246 $applicationsInstalled = DAL::isInstalledApplications($domainId);
2247
2248 #-----------------------------------------------------------------
2249 # Information about domain's site applications
2250 # should be extracted prior to database/hosting/custom-buttons/dns-records
2251 # dump, as site applications' linked resources should be dumped
2252 # separately.
2253 #-----------------------------------------------------------------
2254
2255 if ($applicationsInstalled) {
2256 @SiteApplications = SiteApp::getDomainSiteapps($domainId, $self->{dbh});
2257
2258 foreach my $sapp (@SiteApplications) {
2259 foreach my $row ( $sapp->getDatabases() ) {
2260 push @excluded_dbs, $row->{'id'};
2261 }
2262
2263 foreach my $row ( $sapp->getDnsRecords() ) {
2264 push @excluded_dns_records, $row->{'id'};
2265 }
2266 }
2267 }
2268
2269 if ( !$self->{only_mail_dump} ) {
2270 #-----------------------------------------------------------------
2271 # Domain's databases
2272 #-----------------------------------------------------------------
2273 Logging::debug("Dumping domain databases");
2274
2275 $self->_validateDatabaseIncluded($domainId, $domainName);
2276
2277 # Databases without those used in site apps
2278 foreach my $db (@{DAL::getDomainDatabases($domainId, \@excluded_dbs)}) {
2279 eval {
2280 $self->makeDatabaseNode( $db->{'id'}, $domainId, 'domain', undef, undef, $embeddedInfo );
2281 1;
2282 } or do {
2283 $self->checkProgramTerminated();
2284 $self->excludeProblemDatabaseFromBackup( $domainId, $db, $@ );
2285 }
2286 }
2287
2288 Logging::debug("Dumping database users belonging to any database");
2289 $self->{packer}->makeDbUsersToAnyDatabasesNode( $domainId, DAL::getCommonDatabaseUsers( $domainId, $embeddedInfo ) );
2290 } else {
2291 Logging::debug("Skip dumping domain databases due to settings");
2292 }
2293
2294 eval {
2295 # Domain's DNS settings
2296 $self->makeDomainDnsZone( \%domain, \@excluded_dns_records );
2297 if ((!defined $ip) && ( $domainType ne 'vrt_hst' ) ) {
2298 my $preferredIp = $self->{packer}->getDomainARecordIp($domainId);
2299 my $type;
2300 $ip = PleskStructure::getIp4DomainWoHosting($domainId, $preferredIp, \$type);
2301 if ( $ip ) {
2302 foreach my $ipAddress (@{$ip}) {
2303 $self->{packer}->setDomainIP( $domainId, $ipAddress, $type );
2304 }
2305 } else {
2306 my $serviceIps = $self->getServiceIps( $domainId, 'mail', $ip );
2307 if ($serviceIps) {
2308 foreach my $serviceIp (keys %{$serviceIps}) {
2309 $self->{packer}->setDomainIP( $domainId, $serviceIp, $serviceIps->{$serviceIp} );
2310 last;
2311 }
2312 }
2313 }
2314 }
2315 1;
2316 } or do {
2317 $self->excludeProblemDnsZoneFromBackup( $domainId, $@ );
2318 };
2319
2320 $self->{packer}->makeDomainParamsNode($domainId, $domParams);
2321
2322 $self->makeMailListsNode($domainId, $domainAsciiName, $ip);
2323
2324 if ( !$self->{only_mail_dump} ) {
2325 Logging::debug("Dumping domain statistics");
2326
2327 $self->addDomainTraffic($domainId);
2328
2329 $self->addDomainCertificates($domainId, $domainName, defined($domain{'cert_rep_id'}) ? $domain{'cert_rep_id'} : '');
2330 }
2331
2332 my $subscriptionProperties = undef;
2333
2334 $subscriptionProperties = $self->getSubscriptionPropertiesHash($domainId, 'domain');
2335
2336 if (exists $subscriptionProperties->{'phpSettingsId'}) {
2337 my $phpSettingsId = $subscriptionProperties->{'phpSettingsId'};
2338 my %phpSettings = %{DAL::getPhpSettings($phpSettingsId)};
2339 my $phpSettingsCustom = DAL::getPhpSettingsCustom($phpSettingsId);
2340 $phpSettings{'notice'} = $phpSettingsCustom if defined $phpSettingsCustom;
2341 $self->{packer}->setDomainPhpSettingsNode($domainId, \%phpSettings);
2342 }
2343
2344 eval {
2345 my $serviceIps = $self->getServiceIps( $domainId, 'web', $ip);
2346
2347 if ( $domainType eq "vrt_hst" ) {
2348 $self->makePhostingNode( \%domain, $domParams, \@SiteApplications, 0, $serviceIps, $embeddedInfo);
2349 }
2350 elsif ( $domainType eq "std_fwd" ) {
2351 $self->makeShostingNode( \%domain, $serviceIps );
2352 }
2353 elsif ( $domainType eq "frm_fwd" ) {
2354 $self->makeFhostingNode( \%domain, $serviceIps );
2355 }
2356 1;
2357 } or do {
2358 $self->checkProgramTerminated();
2359 $self->excludeProblemHostingFromBackup( $domainId, $domainType, $@ );
2360 };
2361
2362 my $subscriptionNode;
2363
2364 if ( !$self->{only_mail_dump} ) {
2365 $self->getCustomButtonsByOwner( 'domain-admin', $domainId );
2366
2367 $subscriptionNode = $self->getSubscription('domain', $domainId);
2368 $self->{packer}->dumpUnityMobileIntegration($domainId, $domParams);
2369 $self->getSubscriptionProperties('domain', $domainId);
2370 $self->dumpApsBundle($domainId, 'domain');
2371
2372 my @defaultDbServers;
2373 my @availableTypes = ('default_server_mysql','default_server_postgresql');
2374 foreach my $defaultDbServerType (@availableTypes) {
2375 if ( exists $subscriptionProperties->{$defaultDbServerType}) {
2376 foreach my $ptrHash (@{DAL::getDatabaseServers()}) {
2377 if ($subscriptionProperties->{$defaultDbServerType} == $ptrHash->{'id'}) {
2378 push @defaultDbServers, $ptrHash;
2379 }
2380 }
2381 }
2382 }
2383
2384 if (@defaultDbServers) {
2385 $self->{packer}->makeDomainDefaultDbServersNode($domainId, \@defaultDbServers);
2386 }
2387
2388 if (ref($subscriptionNode) =~ /XmlNode/) {
2389 $self->{packer}->makeSubscriptionPropertiesNode($subscriptionNode, $subscriptionProperties);
2390 }
2391
2392 if ($applicationsInstalled) {
2393 foreach my $sapp (@SiteApplications) {
2394 my $apsRegistryId = $sapp->getApplicationApsRegistryId();
2395 foreach my $row ( $sapp->getMailUsers() ) {
2396 $self->{packer}->assignApplicationInfoToMailUser($apsRegistryId, $row);
2397 }
2398 }
2399 }
2400 }
2401
2402 $self->{suspender}->unSuspendDomain();
2403
2404 if ( exists $domainPtr->{'description'} ) {
2405 $self->{packer}->makeDomainDescriptionsNode( $domainId, $domainPtr->{'description'} );
2406 }
2407
2408 if (!$self->{only_mail_dump}) {
2409 $self->{packer}->setComposerInstances($domainId, $embeddedInfo);
2410 }
2411
2412 $self->{packer}->makeExtensionNode('subscription', $domainId);
2413
2414 $self->{packer}->{stat}{dbDumpsCount}++ if ($self->{isAnyDbDumpedOnDomain} == 1);
2415
2416 $self->{dump_status}->endDomain($domainName);
2417 $self->{packer}->finishDomain($domainId);
2418 Logging::endObject();
2419}
2420
2421sub dumpMailSystem {
2422 my ( $self, $parentType, $domParams, $domain, $isroot, $ip ) = @_;
2423
2424 $self->checkProgramTerminated();
2425
2426 Logging::debug("Dumping domain mailsystem");
2427
2428 my $domainId = $domain->{'id'};
2429 my $domainName = $domain->{'displayName'};
2430 my $domainAsciiName = $domain->{'name'};
2431 my $isSite = exists $domain->{'webspace_id'} ? $domain->{'webspace_id'} ne '0' : 0;
2432
2433 my $mailServiceStatus = $self->getDomainMailStatus($domainId);
2434 if ( defined($mailServiceStatus) ) {
2435 my $serviceIps = $self->getServiceIps( $domainId, 'mail', $ip );
2436 $self->{packer}->setDomainMailService( $domainId, $mailServiceStatus, $serviceIps );
2437
2438 my @mails = @{DAL::getDomainMails($domainId)};
2439 if ( @mails ) {
2440
2441 if ($self->{dump_full_mail}) {
2442 $self->{packer}->setDomainMailNamesContent( $domainId, $domainName,
2443 AgentConfig::getPleskMailnamesDir($domainAsciiName, undef),
2444 AgentConfig::mailContentUser());
2445 }
2446
2447 foreach my $ptrRow (@mails) {
2448 $ptrRow->[2] = CommonPacker::normalizePasswordType( $ptrRow->[2] );
2449 eval {
2450 $self->makeMailUserNode( $domainId, $ptrRow->[0], $ptrRow->[1], $ptrRow->[2], $domainName, $domainAsciiName, $parentType, $domain->{'cl_id'} );
2451 1;
2452 } or do {
2453 $self->excludeProblemMailUserFromBackup( $domainId, $ptrRow, $@ );
2454 }
2455 }
2456 $self->{packer}->removeMailSystemChildNodeIfEmpty( $domainId, 'mailuser' );
2457 }
2458
2459 $self->getCatchAllAddress($domainId);
2460
2461 $self->getDomainKeysDomainSupport( $domainId, $domainName, $domain->{'dns_zone_id'} );
2462
2463 my $oldWebMailFlag = undef;
2464 my $webmail = exists $domParams->{'webmail'} ? $domParams->{'webmail'} : defined($oldWebMailFlag) ? 'horde' : 'none';
2465 my $cert = undef;
2466 if (exists $domParams->{'webmail_certificate_id'}) {
2467 my $pk = $self->getDomainCertificatePrivateKey($domParams->{'webmail_certificate_id'}, $domainId);
2468 $cert = $self->getCertificateRef($pk);
2469 }
2470
2471 $self->{packer}->setDomainWebMail( $domainId, $webmail, $cert );
2472 $self->{packer}->setDomainGLSupport( $domainId, (exists $domParams->{'gl_filter'} ) ? $domParams->{'gl_filter'} : 'on' );
2473
2474 my $sql = "SELECT `parameter`, `value` FROM Parameters INNER JOIN DomainServices ON Parameters.id = DomainServices.parameters_id WHERE DomainServices.dom_id = ? AND Parameters.`parameter` LIKE 'outgoing_messages_%'";
2475 if ( $self->{dbh}->execute_rownum($sql, $domainId) ) {
2476 while (my $ptrRow = $self->{dbh}->fetchrow() ) {
2477 $self->{packer}->makeOutgoingMessagesParameter('mailsystem', $domainId, $ptrRow->[0], $ptrRow->[1]);
2478 }
2479 }
2480 $self->{dbh}->finish();
2481
2482 }
2483}
2484
2485sub getDomainMailStatus {
2486 my ($self, $domainId) = @_;
2487 return DAL::getDomainServiceStatus( $domainId, 'mail' );
2488}
2489
2490sub getDomainMaillistStatus {
2491 my ($self, $domainId) = @_;
2492 return DAL::getDomainServiceStatus( $domainId, 'maillists' );
2493}
2494
2495sub getDomainDefaultCert {
2496 my $self = shift;
2497 return DAL::getDomainDefaultCert102(@_);
2498}
2499
2500sub makeSiteNode {
2501 my ( $self, $domainAsciiName, $domainName, $ptrApplications, $embeddedInfo ) = @_;
2502
2503 $self->checkProgramTerminated();
2504
2505 my ( $sql, $ptrHash );
2506
2507 Logging::beginObject( 'domain', $domainName, $self->generateObjectUuidForLogging( 'domain', $domainName ) );
2508
2509 my $domainPtr = DAL::getDomainPtrByAsciiName($domainAsciiName);
2510 unless( $domainPtr ) {
2511 Logging::error("Failed to get domain hash for '$domainName'",'PleskDbError');
2512 Logging::endObject();
2513 return;
2514 }
2515 my %domain = %{$domainPtr};
2516
2517 my $domainId = $domain{'id'};
2518 my $webspaceId = $domain{'webspace_id'};
2519
2520 my $domainType = $domain{'htype'};
2521
2522 my $domainOwner = PleskStructure::getClientNameFromId( $domain{'cl_id'} );
2523 my $parentType = PleskStructure::getClientType( $domainOwner );
2524
2525
2526 $self->{packer}->addDomainSite( $webspaceId, $domainId, $domainAsciiName, $domainName, \%domain );
2527
2528 $self->{suspender}->suspendDomain( $domainName );
2529
2530 $self->addWwwStatus( $domainId, $domainAsciiName );
2531
2532 #
2533 # Status
2534 #
2535 Logging::debug("Dumping site status");
2536
2537 my $status = $domain{'status'};
2538 $self->{packer}->setDomainStatus( $domainId, $status );
2539
2540 if ( !$self->{only_mail_dump} ) {
2541 # Domain's aliases
2542 $self->dumpDomainAliases($domainId);
2543 }
2544
2545 #
2546 # No further info required if shallow dump specified
2547 #
2548 if ( $self->{shallow_dump} && !$self->{only_mail_dump} ) {
2549 $self->{suspender}->unSuspendDomain();
2550 $self->{packer}->finishDomain($domainId);
2551 Logging::endObject();
2552 return;
2553 }
2554
2555 my $domParams = $self->getDomainParams(\%domain);
2556
2557 if ( !$self->{only_hosting_dump} ) {
2558 eval {
2559 $self->dumpMailSystem($parentType, $domParams, \%domain, 0, undef);
2560 1;
2561 } or do {
2562 $self->checkProgramTerminated();
2563 $self->excludeProblemMailSystemFromBackup( $domainId, $@ );
2564 }
2565 }
2566 else { Logging::debug("Skip site mailsystem dump due to settings"); }
2567
2568 my @SiteApplications;
2569 my @excluded_dbs;
2570 my @excluded_dns_records;
2571 my $applicationsInstalled = 1;
2572
2573 $applicationsInstalled = DAL::isInstalledApplications($webspaceId);
2574
2575 #-----------------------------------------------------------------
2576 # Information about domain's site applications
2577 # should be extracted prior to database/hosting/custom-buttons/dns-records
2578 # dump, as site applications' linked resources should be dumped
2579 # separately.
2580 #-----------------------------------------------------------------
2581
2582 if ($applicationsInstalled) {
2583
2584 @SiteApplications = @{$ptrApplications};
2585
2586 foreach my $sapp (@SiteApplications) {
2587 foreach my $row ( $sapp->getDatabases() ) {
2588 push @excluded_dbs, $row->{'id'};
2589 }
2590
2591 foreach my $row ( $sapp->getDnsRecords() ) {
2592 push @excluded_dns_records, $row->{'id'};
2593 }
2594 }
2595 }
2596
2597 eval {
2598 # Domain's DNS settings
2599 $self->makeDomainDnsZone( \%domain, \@excluded_dns_records );
2600 1;
2601 } or do {
2602 $self->excludeProblemDnsZoneFromBackup( $domainId, $@ );
2603 };
2604
2605 $self->{packer}->makeDomainParamsNode($domainId, $domParams);
2606
2607 $self->makeMailListsNode($domainId, $domainAsciiName);
2608
2609 if ( !$self->{only_mail_dump} ) {
2610 Logging::debug("Dumping site statistics");
2611
2612 $self->addDomainTraffic($domainId);
2613
2614 $self->addDomainCertificates($domainId, $domainName, defined($domain{'cert_rep_id'}) ? $domain{'cert_rep_id'} : '');
2615
2616 if ( $domainType eq "vrt_hst" ) {
2617 $self->makePhostingNode( \%domain, $domParams, \@SiteApplications, 1, undef, $embeddedInfo );
2618 }
2619 elsif ( $domainType eq "std_fwd" ) {
2620 $self->makeShostingNode( \%domain );
2621 }
2622 elsif ( $domainType eq "frm_fwd" ) {
2623 $self->makeFhostingNode( \%domain );
2624 }
2625
2626 $self->getCustomButtonsByOwner( 'domain-admin', $domainId );
2627
2628 $self->getSubscription('domain', $domainId);
2629 $self->{packer}->dumpUnityMobileIntegration($domainId, $domParams);
2630 }
2631
2632 if ( exists $domainPtr->{'description'} ) {
2633 $self->{packer}->makeDomainDescriptionsNode( $domainId, $domainPtr->{'description'} );
2634 }
2635
2636 $self->{packer}->makeExtensionNode('site', $domainId);
2637 $self->{suspender}->unSuspendDomain();
2638 $self->{packer}->finishDomain($domainId);
2639 Logging::endObject();
2640}
2641
2642sub makeDomainDnsZone {
2643 my ( $self, $domainHashPtr, $excludedRecordsPtr) = @_;
2644
2645 Logging::debug("Dumping domain DNS");
2646
2647 # dns_zone_id could be null for wildcard subdomains
2648 if ( $domainHashPtr->{'dns_zone_id'} != 0) {
2649 return $self->makeDnsZone( $domainHashPtr->{'dns_zone_id'}, $domainHashPtr->{'id'}, 'domain', $excludedRecordsPtr );
2650 }
2651}
2652
2653sub makeDnsRecord {
2654 my ( $self, $ptrHash) = @_;
2655
2656 return unless $ptrHash->{'type'} =~ /^A|AAAA|NS|MX|CNAME|PTR|TXT|master|SRV|AXFR|DS|CAA$/;
2657
2658 if ( $ptrHash->{'type'} eq 'TXT' ) {
2659 $ptrHash->{'val'} =~ s/"(.*)"/$1/;
2660 }
2661
2662 # Fix broken CNAME mail records (bug #110731)
2663 if ( $ptrHash->{'type'} eq 'CNAME'
2664 and $ptrHash->{'host'} eq "mail." . $ptrHash->{'val'} )
2665 {
2666 $ptrHash->{'type'} = 'A';
2667 $ptrHash->{'val'} =~ s/\.$//;
2668 if (defined($ptrHash->{'displayVal'})) {
2669 delete($ptrHash->{'displayVal'});
2670 }
2671 my $ips = PleskStructure::getDomainIp( $ptrHash->{'val'} ) ;
2672 foreach my $ip (@{$ips}) {
2673 if ($ip =~/^\d+\.\d+\.\d+\.\d+$/) {
2674 $ptrHash->{'val'} = $ip;
2675 }
2676 }
2677 }
2678
2679 return %{$ptrHash};
2680}
2681
2682sub geteDnsZone {
2683 my ( $self, $dnsZoneId, $paramsPtr, $recordsPtr, $excludedRecordsPtr ) = @_;
2684
2685 my $sql = "SELECT * FROM dns_zone WHERE id=?";
2686
2687 if ( !$self->{dbh}->execute_rownum($sql, $dnsZoneId) ) {
2688 $self->{dbh}->finish();
2689 my $msg = "Broken referencial integrity: DNS zone id $dnsZoneId is not found in dns_zone";
2690 print STDERR "$msg\n";
2691 Logging::warning($msg,'BrokenDbIntegrity');
2692 return;
2693 }
2694
2695 if ( my $hashPtr = $self->{dbh}->fetchhash($sql) ) {
2696 %{$paramsPtr} = %{ $hashPtr };
2697 }
2698
2699 $self->{dbh}->finish();
2700
2701 $sql = "SELECT dns_recs.*, dns_refs.status FROM dns_recs LEFT OUTER JOIN dns_refs ON dns_refs.zoneRecordId = dns_recs.id WHERE dns_zone_id = ?";
2702 my @sqlParams = ($dnsZoneId);
2703 if( ref($excludedRecordsPtr) =~ /ARRAY/ ) {
2704 my @excludeIds = @{$excludedRecordsPtr};
2705 if ( @excludeIds ) {
2706 $sql .= " AND id NOT IN (" . join(',', ("?")x@excludeIds) . ")";
2707 @sqlParams = (@sqlParams, @excludeIds);
2708 }
2709 }
2710
2711 if ( $self->{dbh}->execute_rownum($sql, @sqlParams) ) {
2712
2713 while ( my $ptrHash = $self->{dbh}->fetchhash() ) {
2714 my %dnsrec = $self->makeDnsRecord($ptrHash);
2715 if (%dnsrec) {
2716 push @{$recordsPtr}, \%dnsrec;
2717 }
2718 }
2719 }
2720 $self->{dbh}->finish();
2721}
2722
2723sub makeDnsZone{
2724 my ( $self, $dnsZoneId, $parent, $parentType, $excludedRecordsPtr ) = @_;
2725
2726 my %params;
2727 my @records;
2728 $self->geteDnsZone( $dnsZoneId, \%params, \@records, $excludedRecordsPtr );
2729
2730 if ( 'domain' eq $parentType ) {
2731 $self->{packer}->setDomainDnsZone( $parent, \%params, \@records );
2732 }
2733 else {
2734 Logging::warning('Error: makeDnsZone: Unexpected type of parent \"$parentType\"','assert');
2735 }
2736}
2737
2738sub dumpDomainAliases {
2739 my ( $self, $domainId ) = @_;
2740
2741 Logging::debug( 'Dumping domain aliases... ', 1 );
2742
2743 my $aliases = DAL::getDomainAliases($domainId);
2744
2745 foreach my $alias (@{$aliases}) {
2746
2747 my %params;
2748 my @records;
2749 if ( $alias->{'dns_zone_id'} != 0 ) {
2750 $self->geteDnsZone( $alias->{'dns_zone_id'}, \%params, \@records );
2751 }
2752
2753 $self->{packer}->addDomainAlias( $domainId, $alias, \%params, \@records );
2754 }
2755
2756 Logging::debug('OK');
2757}
2758
2759sub addWwwStatus {
2760 my ( $self, $domainId, $domainName ) = @_;
2761
2762 my $sql;
2763
2764 # Domain is considered to have 'www' prefix when there is 'CNAME', 'A' or 'AAAA' record with 'www' name.
2765 # While domain has CNAME record Plesk prohibits creation of 'www' alias or subdomain.
2766 # If user remove CNAME records then it may create 'www' alias and 'www' A-records will be added to zone.
2767 # When deployer will restore backup of such domain then it will first create CNAME record (due to 'www' domain flag)
2768 # and then it will try to restore 'www' alias and will fail due to conflict.
2769 # So 'www' flag for domain is set only if CNAME records is found, 'A' and 'AAAA' are not checked.
2770 $sql = "SELECT r.* FROM dns_recs r, domains d WHERE d.id=? "
2771 . "AND d.dns_zone_id=r.dns_zone_id AND r.type = 'CNAME' AND r.host = '?'";
2772
2773 if ( $self->{dbh}->execute_rownum($sql, $domainId, "www.$domainName.") ) {
2774 $self->{packer}->setDomainWwwStatus( $domainId, 'true' );
2775 }
2776 else {
2777 $self->{packer}->setDomainWwwStatus( $domainId, 'false' );
2778 }
2779 $self->{dbh}->finish();
2780}
2781
2782sub addSpecificUserAndRole {
2783 my ( $self, $parentType, $userName, $roleName, $userHash, $rolePermsHash, $ownerId ) = @_;
2784
2785 my $callback;
2786 eval {
2787 if( $parentType eq 'root' ) {
2788 $callback = sub {
2789 $self->{packer}->removeRootUser( @_ );
2790 };
2791 $self->{packer}->addRootUser( $userName, $userHash);
2792 }
2793 elsif( $parentType eq 'admin' ) {
2794 $callback = sub {
2795 $self->{packer}->removeAdminUser( @_ );
2796 };
2797 $self->{packer}->addAdminUser( $userName, $userHash);
2798 }
2799 elsif( $parentType eq 'reseller' || $parentType eq 'client') {
2800 $callback = sub {
2801 $self->{packer}->removeClientUser( $ownerId, @_ );
2802 };
2803 $self->{packer}->addClientUser( $ownerId, $userName, $userHash);
2804 }
2805 1;
2806 } or do {
2807 $self->excludeProblemUserFromBackup( $userName, $callback, $@ );
2808 };
2809
2810 eval {
2811 if( $parentType eq 'root' ) {
2812 $callback = sub {
2813 $self->{packer}->removeRootRole( @_ );
2814 };
2815 $self->{packer}->addRootRole( $roleName, 0, $rolePermsHash, []);
2816 }
2817 elsif( $parentType eq 'admin' ) {
2818 $callback = sub {
2819 $self->{packer}->removeAdminRole( @_ );
2820 };
2821 $self->{packer}->addAdminRole( $roleName, 0, $rolePermsHash, []);
2822 }
2823 elsif( $parentType eq 'reseller' || $parentType eq 'client') {
2824 $callback = sub {
2825 $self->{packer}->removeClientRole( $ownerId, @_ );
2826 };
2827 $self->{packer}->addClientRole( $ownerId, $roleName, 0, $rolePermsHash, []);
2828 }
2829 1;
2830 } or do {
2831 $self->excludeProblemRoleFromBackup( $callback, $roleName, $@ );
2832 };
2833}
2834
2835sub getTrafficValue {
2836 my ( $self, $tableName, $idName, $idValue ) = @_;
2837
2838 my $trafficValue = '';
2839
2840 my $sql = "SELECT http_in, http_out, ftp_in, ftp_out, smtp_in, smtp_out, "
2841 . "pop3_imap_in, pop3_imap_out, date FROM $tableName WHERE $idName = ?";
2842
2843 if ( $self->{dbh}->execute_rownum($sql, $idValue) ) {
2844 my @keys = ( 'http', 'ftp', 'smtp', 'pop3-imap' );
2845 my ( $key, $i, $ptrRow );
2846 while ( $ptrRow = $self->{dbh}->fetchrow() ) {
2847 for ( $i = 0 ; $i < @keys * 2 ; ++$i ) {
2848 if ( $ptrRow->[$i] ) {
2849 $trafficValue .= $ptrRow->[8];
2850 $trafficValue .= ' ';
2851 $trafficValue .= $keys[ $i / 2 ];
2852 $trafficValue .= ' ';
2853 $trafficValue .= ( $i % 2 ? 'out' : 'in' );
2854 $trafficValue .= ' ';
2855 $trafficValue .= $ptrRow->[$i];
2856 $trafficValue .= "\n";
2857 }
2858 }
2859 }
2860 }
2861 $self->{dbh}->finish();
2862 return $trafficValue;
2863}
2864
2865#
2866# addDomainTraffic - add current traffic
2867#
2868# arguments:
2869# $domainId - ID of domain
2870#
2871sub addDomainTraffic {
2872 my ( $self, $domainId ) = @_;
2873
2874 my $trafficValue = '';
2875
2876 $trafficValue = $self->getTrafficValue( 'DomainsTraffic', 'dom_id', $domainId );
2877
2878 $self->{packer}->setDomainTraffic( $domainId, $trafficValue ) if $trafficValue;
2879}
2880
2881sub addDomainCertificates {
2882 my ($self, $domainId, $domainName, $domainCertRepId) = @_;
2883
2884 my @defaultCerts = @{$self->getDomainDefaultCert($domainId)};
2885 my @domainCerts = @{DAL::getCertificateIds($domainCertRepId)};
2886 foreach my $id (@domainCerts) {
2887 $self->makeCertificateNode($id, $domainId, 'domain', grep {$_ eq $id} @defaultCerts ? 1 : 0);
2888 }
2889
2890 if ($self->{include_app_distrib}) {
2891 my %hostingParams = %{DAL::getHostingParams($domainId)};
2892 if (exists($hostingParams{'certificate_id'}) and $hostingParams{'certificate_id'} != 0) {
2893 my $id = $hostingParams{'certificate_id'};
2894 if (!(grep {$_ eq $id} @domainCerts)) {
2895 $self->{packer}->setServerSettings() unless defined $self->{packer}->{serverNode};
2896 $self->makeCertificateNode($id, 0, 'server', 0);
2897 }
2898 } else {
2899 foreach my $id (@defaultCerts) {
2900 if (!(grep {$_ eq $id} @domainCerts)) {
2901 $self->{packer}->setServerSettings() unless defined $self->{packer}->{serverNode};
2902 $self->makeCertificateNode($id, 0, 'server', 0);
2903 }
2904 }
2905 }
2906 }
2907}
2908
2909sub addClientTraffic {
2910 my ( $self, $clientId ) = @_;
2911
2912 my $trafficValue = '';
2913
2914 $trafficValue = $self->getTrafficValue( 'ClientsTraffic', 'cl_id', $clientId );
2915 $self->{packer}->setClientTraffic( $clientId, $trafficValue ) if $trafficValue;
2916}
2917
2918# There are 3 types of nonexistent user mail handling:
2919# Bounce with message (bounce:message text)
2920# Catch to address (email@address)
2921# SMTP reject (reject)
2922# Returns bounce|catch|reject or empty string
2923sub getNonexistentMode {
2924 my ( $self, $domainId ) = @_;
2925
2926 my $sql = "SELECT p.value FROM Parameters p, DomainServices ds "
2927 . "WHERE ds.parameters_id = p.id AND ds.dom_id = ? AND p.parameter = 'nonexist_mail'";
2928 my $mode;
2929 if ( $self->{dbh}->execute_rownum($sql, $domainId) ) {
2930 if (my $rowPtr = $self->{dbh}->fetchrow()) {
2931 $mode = @{ $rowPtr }[0];
2932 }
2933 }
2934 else {
2935 $mode = "bounce:This address no longer accepts mail.";
2936 }
2937 $self->{dbh}->finish();
2938
2939 return $mode;
2940}
2941
2942sub getCatchAllAddress {
2943 my ( $self, $domainId ) = @_;
2944
2945 my $sql;
2946 my @sqlParams = ();
2947
2948 my $mode = $self->getNonexistentMode($domainId);
2949
2950 if ( $mode =~ /^catch$/ ) {
2951 $sql = "SELECT p.value FROM Parameters p, DomainServices ds "
2952 . "WHERE ds.parameters_id = p.id AND ds.dom_id = ? AND p.parameter = 'catch_addr'";
2953 push(@sqlParams, $domainId);
2954 }
2955 elsif ( $mode =~ /^bounce$/ ) {
2956 $sql = "SELECT CONCAT('bounce:', p.value) FROM Parameters p, DomainServices ds "
2957 . "WHERE ds.parameters_id = p.id AND ds.dom_id = ? AND p.parameter = 'bounce_mess'";
2958 push(@sqlParams, $domainId);
2959 }
2960 elsif ( $mode =~ /^reject$/ ) {
2961 $sql = "SELECT 'reject'";
2962 }
2963
2964 # some not supported mode or default parameter [bug 43901]
2965 return unless ($sql);
2966
2967 if ( $self->{dbh}->execute_rownum($sql, @sqlParams) ) {
2968 if ( my $rowPtr = $self->{dbh}->fetchrow() ) {
2969 my $catchAllAddr = @{ $rowPtr }[0];
2970 if ($catchAllAddr) {
2971 $self->{packer}->setDomainCatchMail( $domainId, $catchAllAddr );
2972 }
2973 }
2974 }
2975 $self->{dbh}->finish();
2976}
2977
2978sub makeMailmanMailListNode {
2979 my ( $self, $domainId, $mlistId, $mlistName, $mlistState ) = @_;
2980
2981 unless ( defined Mailman::version() ) {
2982 Logging::debug("Unable to found Mailman installation");
2983 return;
2984 }
2985
2986 my @owners = Mailman::getListOwners($mlistName);
2987 if ( !@owners ) {
2988 Logging::debug("Bad maillist $mlistName, skipped");
2989 return;
2990 }
2991
2992 my %listMembers = Mailman::getListMembers($mlistName);
2993
2994 $self->{packer}->addDomainMailList( $domainId, $mlistName,
2995 Mailman::getListPassword($mlistName),
2996 $mlistState, \@owners, \%listMembers );
2997}
2998
2999my %dumpedCerts;
3000
3001sub makeCertificateNode {
3002 my ( $self, $certId, $parent, $parentType, $default ) = @_;
3003
3004 return if $dumpedCerts{$certId};
3005
3006 my ( $sql, %cert, $item );
3007
3008 $sql = "SELECT * FROM certificates WHERE id=?";
3009 unless ( $self->{dbh}->execute_rownum($sql, $certId) ) {
3010 $self->{dbh}->finish();
3011 my $msg = "Broken referencial integrity: certificate ID '$certId' is not found";
3012 print STDERR "$msg\n";
3013 Logging::warning($msg,'BrokenDbIntegrity');
3014 return;
3015 }
3016
3017 if ( my $hashPtr = $self->{dbh}->fetchhash() ) {
3018 %cert = %{ $hashPtr };
3019 }
3020 $self->{dbh}->finish();
3021
3022 my $cert;
3023 my $csr;
3024 my $ca_cert;
3025 my $name;
3026
3027 $cert = $cert{'cert'};
3028 $csr = $cert{'csr'};
3029 $ca_cert = $cert{'ca_cert'};
3030
3031 $name = $cert{'name'};
3032
3033 my $pvt_key = $cert{'pvt_key'};
3034
3035 if ( 'server' eq $parentType ) {
3036 $self->{packer}->addServerCertificate( $name, $cert, $csr, $ca_cert, $pvt_key, $default );
3037 }
3038 elsif ( 'domain' eq $parentType ) {
3039 $self->{packer}->addDomainCertificate( $parent, $name, $cert, $csr, $ca_cert, $pvt_key, $default );
3040 }
3041 else {
3042 Logging::warning('Error: makeCertificateNode: unexpected parent type','assert');
3043 }
3044 $dumpedCerts{$certId} = 1;
3045}
3046
3047sub makeDatabaseNode {
3048 my ( $self, $dbId, $parent, $parentType, $sappId, $sappDb, $embeddedInfo ) = @_;
3049
3050 $self->checkProgramTerminated();
3051
3052 my ( $ptrHash, $item, $charset, $dbServerId, $dbServerHost, $dbServerPort, $skipContent, $dbServerVersion );
3053
3054 $skipContent = 0;
3055
3056 my $dbRow;
3057 my $sql = "SELECT name, type, external_id, host FROM data_bases AS d LEFT JOIN DatabaseCustomHosts AS h ON d.id=h.id WHERE d.id = ?";
3058 unless ( ( $self->{dbh}->execute_rownum($sql, $dbId) ) && ( $dbRow = $self->{dbh}->fetchrow() ) ) {
3059 $self->{dbh}->finish();
3060 my $msg = "Broken referencial integrity: Database id $dbId is not found in data_bases";
3061 print STDERR "$msg\n";
3062 Logging::warning($msg ,'BrokenDbIntegrity');
3063 return;
3064 }
3065 my ( $dbName, $dbType ) = @{ $dbRow };
3066 my %optional;
3067 $optional{'external_id'} = $dbRow->[2];
3068 $optional{'custom-host'} = $dbRow->[3];
3069 $self->{dbh}->finish();
3070
3071 $dbName = HelpFuncs::trim($dbName);
3072
3073 if (!$self->_isDatabaseIncluded($dbId)) {
3074 Logging::debug("Database #$dbId '$dbName' is not included, skip it.");
3075 return;
3076 }
3077
3078 Logging::beginObject($dbType,$dbName, undef);
3079
3080 if ( $dbType eq "postgres" or $dbType eq "postgresql" ) {
3081 $dbType = "postgresql";
3082 }
3083
3084 my %dbServer;
3085
3086 $sql = "SELECT host, port, ds.type, ds.server_version FROM DatabaseServers as ds, data_bases as db WHERE "
3087 . "ds.id = db.db_server_id AND db.id = ?";
3088 if ( $self->{dbh}->execute_rownum($sql, $dbId) ) {
3089 if( my $ptrRow = $self->{dbh}->fetchrow() ) {
3090 $dbServerHost = ( $ptrRow->[0] ne 'localhost' ) ? $ptrRow->[0] : 'localhost';
3091 $dbServerPort = $ptrRow->[1];
3092 $dbServerVersion = $ptrRow->[3];
3093
3094 $dbServer{'type'} = $ptrRow->[2];
3095 $dbServer{'host'} = $ptrRow->[0];
3096 $dbServer{'port'} = $ptrRow->[1];
3097 }
3098 }
3099 $self->{dbh}->finish();
3100
3101 my @dbUsers;
3102 if ( defined $sappDb ) {
3103 $optional{'sapp-param'} = $sappDb->{'param'} if ($sappDb->{'param'});
3104 $optional{'aps-registry-id'} = $sappDb->{'apsRegistryId'} if exists $sappDb->{'apsRegistryId'};
3105 $optional{'db-existent'} = $sappDb->{'db-existent'} if exists $sappDb->{'db-existent'};
3106 $optional{'prefix'} = $sappDb->{'prefix'} if exists $sappDb->{'prefix'};
3107 }
3108 my %contentDescription;
3109
3110 if ( !$self->{shallow_dump} ) {
3111 Logging::debug("Database $dbName");
3112
3113 foreach my $dbUserHash ( @{DAL::getDatabaseUsers( $dbId, $embeddedInfo )} ) {
3114 $dbUserHash->{'password'} ||= ''; # NULL -> ''
3115 my %item;
3116 $item{'login'} = $dbUserHash->{'login'};
3117 $item{'password'} = $dbUserHash->{'password'};
3118 $item{'type'} = CommonPacker::normalizePasswordType( $dbUserHash->{'type'} );
3119 $item{'id'} = $dbUserHash->{'id'};
3120 $item{'external_id'} = $dbUserHash->{'external_id'} if $dbUserHash->{'external_id'};
3121 if ( defined $sappDb->{'apsCreatedUser'} and $sappDb->{'apsCreatedUser'} eq $dbUserHash->{'login'} ) {
3122 $item{'aps-registry-id'} = $sappDb->{'apsRegistryId'};
3123 }
3124
3125 if (exists $dbUserHash->{'default_user_id'} && $dbUserHash->{'default_user_id'} eq $dbUserHash->{'id'}) {
3126 $item{'default'} = '';
3127 }
3128
3129 if (defined $sappDb && exists $sappDb->{'db-user-existent'}) {
3130 $item{'db-user-existent'} = $sappDb->{'db-user-existent'};
3131 }
3132
3133 if (exists $dbUserHash->{'acl'}) {
3134 $item{'acl'} = $dbUserHash->{'acl'};
3135 }
3136 if (exists($dbUserHash->{'privileges'})) {
3137 $item{'privileges'} = $dbUserHash->{'privileges'};
3138 }
3139
3140 push @dbUsers, \%item;
3141 }
3142
3143 my ( $dbUser, $dbPasswd );
3144
3145 $sql = "SELECT admin_login, admin_password, ds.id FROM DatabaseServers as ds, data_bases as db "
3146 . "WHERE ds.id = db.db_server_id AND db.id = ?";
3147 my $ptrRow;
3148 unless ( ( $self->{dbh}->execute_rownum($sql, $dbId) ) && ( $ptrRow = $self->{dbh}->fetchrow() ) ) {
3149 $self->{dbh}->finish();
3150 my $msg = "Broken referencial integrity: DatabaseServers vs data_bases for db id $dbId";
3151 print STDERR "$msg\n";
3152 Logging::warning($msg ,'BrokenDbIntegrity');
3153 return;
3154 }
3155 ( $dbUser, $dbPasswd, $dbServerId ) = @{ $ptrRow };
3156 $self->{dbh}->finish();
3157
3158 my %dbServerInfo;
3159 $dbServerInfo{'id'} = $dbServerId;
3160 $dbServerInfo{'type'} = $dbType;
3161 $dbServerInfo{'host'} = $dbServerHost;
3162 $dbServerInfo{'admin_password'} = $dbPasswd;
3163
3164 $dbPasswd = PleskStructure::getDbServerAdminPassword(\%dbServerInfo);
3165 if (not defined $dbPasswd) {
3166 Logging::error("Unable to define superuser password for ". $dbType ." server on ". $dbServerHost);
3167 return;
3168 }
3169
3170 if ( $dbType eq "postgresql" ) {
3171 $optional{'version'} = $dbServerVersion ne '' ? $dbServerVersion : AgentConfig::getPostgresqlVersion();
3172 }
3173
3174 if ( $dbType eq "mysql" ) {
3175 $optional{'version'} = $dbServerVersion ne '' ? $dbServerVersion : Db::MysqlUtils::getVersion();
3176 }
3177
3178 %contentDescription = (
3179 "name" => $dbName,
3180 'tables' => undef,
3181 "type" => $dbType,
3182 "user" => $dbUser,
3183 "password" => $dbPasswd,
3184 "host" => $dbServerHost,
3185 "port" => $dbServerPort,
3186 "plesk_7" => 0
3187 );
3188
3189 if ( $dbType eq "postgresql" ) {
3190 my $psql = AgentConfig::psqlBin();
3191 if ( -e $psql ) {
3192#[Bug 119082]
3193#$charset = `PGUSER=$dbUser PGPASSWORD='$dbPasswd' $psql -l template1 | grep '^[ \t]*$dbName ' | awk '{print \$5}'`;
3194 my $wrapPgsql = Db::DbConnect::getDbConnect(
3195 $dbType, $dbUser, $dbPasswd, $dbName,
3196 $dbServerHost, undef, undef, undef,
3197 undef, $dbServerPort
3198 );
3199 if ( ref($wrapPgsql) eq 'HASH' ) {
3200 if (
3201 $wrapPgsql->{'EXECUTE'}->( "select pg_catalog.pg_encoding_to_char(d.encoding) FROM pg_catalog.pg_database d where d.datname='?'", $dbName )
3202 )
3203 {
3204 my $ptrRow;
3205 if ( ( $ptrRow = $wrapPgsql->{'FETCHROW'}->() ) ) {
3206 $charset = $ptrRow->[0];
3207 if ( $charset ne '' ) {
3208 $optional{'charset'} = $charset;
3209 }
3210 }
3211 $wrapPgsql->{'FINISH'}->();
3212 }
3213
3214 my $conn = $wrapPgsql->{'CONNECTION'};
3215 my $existentTables = Db::PostgresqlUtils::getTables($conn);
3216 $contentDescription{'tables'} = $self->_getIncludedDatabaseTables($dbId, $dbName, $existentTables);
3217 }
3218 else {
3219 Logging::warning( "Cannot connect to PostgreSQL $dbServerHost:$dbServerPort (database '$dbName')" );
3220 $skipContent = 1;
3221 }
3222 } else {
3223 Logging::error("The psql command is absent on a server, so the dump of PostgreSQL databases can not be created.");
3224 $skipContent = 1;
3225 }
3226 }
3227
3228 if ( $dbType eq "mysql" ) {
3229 my $wrapMysql = Db::DbConnect::getDbConnect(
3230 $dbType, $dbUser, $dbPasswd, $dbName,
3231 $dbServerHost, undef, undef, undef,
3232 undef, $dbServerPort
3233 );
3234 if ( ref($wrapMysql) eq 'HASH' ) {
3235 if ( $wrapMysql->{'EXECUTE'}->("SHOW VARIABLES LIKE \"character_set_database\"") )
3236 {
3237 my $ptrRow = $wrapMysql->{'FETCHROW'}->();
3238 my $charset;
3239 $charset = $ptrRow->[1] if $ptrRow;
3240 $optional{'charset'} = $charset if $charset;
3241 $wrapMysql->{'FINISH'}->();
3242 }
3243
3244 # We can't always use UTF8 for dump content because it may lead to corruption of latin1-only-databases.
3245 # See http://bugs.plesk.ru/show_bug.cgi?id=134509 for details.
3246 # However, using database charset may also lead to corruption if database has latin1 default
3247 # charset, but some tables or columns have non-latin1 charset.
3248 # The semi-solution is to query charset for tables and columns and if they all have
3249 # the same charset - use it, otherwise use utf-8.
3250 my $conn = $wrapMysql->{'CONNECTION'};
3251 my %collations = Db::MysqlUtils::getCollations( $conn );
3252 my %tablesCollations = Db::MysqlUtils::getTablesCollation( $conn );
3253 my @tablesCharsets = map { $collations{$_} } values(%tablesCollations);
3254 my %usedCharsets = map { $_, 1 } @tablesCharsets;
3255 for my $table (keys %tablesCollations) {
3256 my %columnsCollations = Db::MysqlUtils::getColumnsCollation( $conn, $table );
3257 $usedCharsets{$collations{$_}} = 1 for (values %columnsCollations);
3258 }
3259
3260 my $dumpCharset = (scalar (keys %usedCharsets) == 1) ? (keys %usedCharsets)[0] : 'utf8';
3261 # ucs2, utf16, and utf32 cannot be used as a client character set (http://dev.mysql.com/doc/refman/5.5/en/charset-connection.html)
3262 # https://jira.plesk.ru/browse/PPP-13515
3263 $dumpCharset = 'utf8' if ($dumpCharset =~ /^(ucs2|utf16|utf32)$/);
3264 $contentDescription{'dump_charset'} = $dumpCharset;
3265
3266 # Dump database collation
3267 if ( $wrapMysql->{'EXECUTE'}->("SHOW VARIABLES LIKE \"collation_database\"") ) {
3268 my $ptrRow = $wrapMysql->{'FETCHROW'}->();
3269 my $collation = $ptrRow->[1] if $ptrRow;
3270 $optional{'collation'} = $collation if $collation;
3271 $wrapMysql->{'FINISH'}->();
3272 }
3273
3274 my @existentTables = keys %tablesCollations;
3275 $contentDescription{'tables'} = $self->_getIncludedDatabaseTables($dbId, $dbName, \@existentTables);
3276 }
3277 else {
3278 Logging::warning( "Cannot connect to mysql $dbServerHost:$dbServerPort (database '$dbName')" );
3279 $skipContent = 1;
3280 }
3281 }
3282
3283 $contentDescription{'create_local_dump'} = $self->checkExistDbServerOnDestination($dbType, $dbServerHost, $dbServerPort);
3284 if ($contentDescription{'create_local_dump'} != 0) {
3285 $contentDescription{'dir_for_local_dump'} = AgentConfig::dumpDir() . '/databases';
3286 }
3287 }
3288
3289 if (defined($contentDescription{'tables'}) and !@{$contentDescription{'tables'}}) {
3290 Logging::debug(sprintf("List of tables of the database '%s' is empty, skip backup of the database content.", $dbName));
3291 $skipContent = 1;
3292 }
3293
3294 $self->{packer}->setContentTransport();
3295
3296 if( $sappId ){
3297 if ( 'domain' eq $parentType ) {
3298 $self->{packer}->addDomainSappDatabase( $dbId, $dbServerId, $parent, $sappId, $dbName, $dbType, \%optional, \%dbServer, \@dbUsers, \%contentDescription, $skipContent );
3299 }
3300 elsif ( 'subdomain' eq $parentType ) {
3301 $self->{packer}->addSubDomainSappDatabase( $dbId, $dbServerId, $parent, $sappId, $dbName, $dbType, \%optional, \%dbServer, \@dbUsers, \%contentDescription, $skipContent );
3302 }
3303 else {
3304 Logging::warning( "Error: makeDatabaseNode: Unexpected type of parent \"$parentType\"",'assert');
3305 }
3306 }
3307 else{
3308 if ( 'domain' eq $parentType ) {
3309 $optional{'related-sites'} = DAL::getDatabaseRelatedSites($dbId, $parent);
3310 $self->{packer}->addDomainDatabase( $dbId, $dbServerId, $parent, $dbName, $dbType, \%optional, \%dbServer, \@dbUsers, \%contentDescription, $skipContent );
3311 }
3312 else {
3313 Logging::warning( "Error: makeDatabaseNode: Unexpected type of parent \"$parentType\"",'assert');
3314 }
3315 }
3316
3317 $self->{isAnyDbDumpedOnDomain} = 1;
3318
3319 Logging::endObject();
3320}
3321
3322sub checkExistDbServerOnDestination {
3323 my ( $self, $type, $host, $port ) = @_;
3324
3325 if ( scalar(@{$self->{existing_remote_db_servers}}) != 0 ) {
3326 foreach my $dbServerString (@{$self->{existing_remote_db_servers}}) {
3327 my ($exType, $exHost, $exPort) = split(/:/, $dbServerString);
3328 if ( $type eq $exType and $host eq $exHost and $port eq $exPort ) {
3329 return 1;
3330 }
3331 }
3332 }
3333
3334 return 0;
3335}
3336
3337sub makeMailUserNode {
3338 my ( $self, $domainId, $mailId, $passwd, $typePasswd, $domainName, $domainAsciiName, $parentType, $clientId ) = @_;
3339
3340 my ( $sql, %mail, $item, $ptrRow, $ptrHash, $dir, $mbox_quota);
3341
3342 $sql = "SELECT * FROM mail WHERE id = ?";
3343 unless ( ( $self->{dbh}->execute_rownum($sql, $mailId) ) && ( $ptrHash = $self->{dbh}->fetchhash() ) ) {
3344 $self->{dbh}->finish();
3345 my $msg = "Broken referencial integrity: Mail id $mailId is not found in mail";
3346 print STDERR "$msg\n";
3347 Logging::warning($msg,'BrokenDbIntegrity');
3348 return;
3349 }
3350 %mail = %{ $ptrHash };
3351 $self->{dbh}->finish();
3352 my $mailName = $mail{'mail_name'};
3353 Logging::beginObject('mailname',$mailName, undef);
3354
3355 my $userUid = undef;
3356 my $cpAccessDefault = undef;
3357 if (exists $mail{'userId'} and $mail{'userId'} != 0) {
3358 $sql = "SELECT uuid, login, email, isLocked FROM smb_users WHERE id = ?";
3359 if ( $self->{dbh}->execute_rownum($sql, $mail{'userId'}) ) {
3360 my $fullMailName = $mailName . "@" . $domainName;
3361 while ( $ptrRow = $self->{dbh}->fetchrow() ) {
3362 $userUid = $ptrRow->[0];
3363 $cpAccessDefault = "true" if ($ptrRow->[3] eq '0' && $ptrRow->[1] eq $fullMailName && $ptrRow->[2] eq $fullMailName);
3364 }
3365 }
3366 $self->{dbh}->finish();
3367 }
3368
3369 $self->{packer}->addMail( $domainId, $mailId, $mailName, $passwd, $typePasswd, $userUid, $cpAccessDefault );
3370
3371 if ( $mail{'mbox_quota'} ) {
3372 $mbox_quota = $mail{'mbox_quota'};
3373
3374 $self->{packer}->setMailBoxQuota( $mailId, $mbox_quota );
3375 }
3376
3377 my $enable_mailbox = $mail{'postbox'} =~ /true/;
3378
3379 # Check whether there autoresponder with attach
3380 # On 'Olde Pleskes' there was bug allowing attaches
3381 # when mailbox in turned off, so we have to explicitly
3382 # turn mailbox on if there is attach.
3383 $sql = "SELECT COUNT(ra.filename) FROM mail_resp AS mr, resp_attach as ra "
3384 . "WHERE ra.rn_id = mr.id AND mr.mn_id = ?";
3385 if ( $self->{dbh}->execute_rownum($sql, $mailId)
3386 and ( $ptrRow = $self->{dbh}->fetchrow() )
3387 and $ptrRow->[0] != 0 )
3388 {
3389 $enable_mailbox = 1;
3390 }
3391 $self->{dbh}->finish();
3392
3393 if ($enable_mailbox) {
3394 $dir = AgentConfig::getPleskMailnamesDir($domainAsciiName, $mailName) . "Maildir";
3395
3396 $self->{packer}->setMailBox( $mailId, $mailName, $domainAsciiName,
3397 ( $mail{'postbox'} =~ /true/ ? 'true' : 'false' ), $dir );
3398 }
3399
3400 #
3401 # aliases
3402 #
3403 $sql = "SELECT alias FROM mail_aliases WHERE mn_id=?";
3404 if ( $self->{dbh}->execute_rownum($sql, $mailId) ) {
3405 while ( $ptrRow = $self->{dbh}->fetchrow() ) {
3406 $self->{packer}->addMailAliase( $mailId, $ptrRow->[0] );
3407 }
3408 }
3409 $self->{dbh}->finish();
3410
3411 #
3412 # end aliases
3413 #
3414
3415 #
3416 # mail forwarding
3417 #
3418
3419 my @members = grep {$_ ne $mailName.'@'.$domainName} @{DAL::getMailRedirects($mailId)};
3420
3421 my $forwarding_enabled = ($mail{'mail_group'} eq 'true');
3422
3423 $self->{packer}->setMailForwarding( $mailId, $forwarding_enabled, \@members );
3424
3425 #
3426 # end mail forwarding
3427 #
3428
3429 #
3430 # autoresponders
3431 #
3432 $dir = AgentConfig::getPleskMailnamesDir($domainAsciiName, $mailName) . "\@attachments";
3433
3434 my (@autos);
3435 $sql = "SELECT id FROM mail_resp WHERE mn_id=? ORDER BY id";
3436 if ( $self->{dbh}->execute_rownum($sql, $mailId) ) {
3437 while ( $ptrRow = $self->{dbh}->fetchrow() ) {
3438 push @autos, $ptrRow->[0];
3439 }
3440 }
3441 $self->{dbh}->finish();
3442
3443 my @autoresponders;
3444 my @filelist;
3445
3446 foreach my $id (@autos) {
3447 my %item = makeAutoresponderNode( $self, $id, $mailName . "@" . $domainName );
3448 push @autoresponders, \%item;
3449 push @filelist, @{$item{'attach'}};
3450 }
3451
3452 $self->{packer}->setMailAutoresponders( $mailId, $mailName, $domainAsciiName, $dir,
3453 $mail{'autoresponder'}, \@autoresponders, \@filelist );
3454 $self->makeAddressbookNode( $mailId, $mailName . '@' . $domainAsciiName );
3455
3456 $dir = AgentConfig::getPleskMailnamesDir($domainAsciiName, $mailName) . ".spamassassin";
3457 $self->makeSpamassassinNode( $mailId, $mail{'mail_name'}, $domainAsciiName, $mail{'spamfilter'}, $dir );
3458
3459 my %states_map = ( 'none' => 'none', 'incoming' => 'in', 'outgoing' => 'out', 'any' => 'inout' );
3460 if ( defined( $states_map{ $mail{'virusfilter'} } ) ) {
3461 $self->{packer}->setMailVirusSettings( $mailId, $states_map{ $mail{'virusfilter'} } );
3462 }
3463
3464
3465 if ( exists $ptrHash->{'description'} ) {
3466 $self->{packer}->makeMailUserDescriptionNode( $mailId, $ptrHash->{'description'} );
3467 }
3468
3469 $self->_makeMailUserOutgoingMessagesNode($mailId);
3470
3471 Logging::endObject();
3472}
3473
3474sub _makeMailUserOutgoingMessagesNode() {
3475 my ($self, $mailUserId) = @_;
3476
3477 my $sql = "SELECT param, val FROM mn_param WHERE mn_id = ? AND param LIKE 'outgoing_messages_%'";
3478 if ($self->{dbh}->execute_rownum($sql, $mailUserId)) {
3479 while (my $ptrRow = $self->{dbh}->fetchrow()) {
3480 $self->{packer}->makeOutgoingMessagesParameter('mailuser', $mailUserId, $ptrRow->[0], $ptrRow->[1]);
3481 }
3482 }
3483 $self->{dbh}->finish();
3484}
3485
3486sub makeAutoresponderNode {
3487 my ( $self, $autoId, $mailName ) = @_;
3488
3489 my ( $name, $value, $sql, %auto, $ptrRow, $item );
3490
3491 $sql = "SELECT * FROM mail_resp WHERE id=?";
3492 unless ( ( $self->{dbh}->execute_rownum($sql, $autoId) ) && ( $ptrRow = $self->{dbh}->fetchhash() ) ) {
3493 $self->{dbh}->finish();
3494 my $msg = "Broken referencial integrity: autoresponder id $autoId is not found in mail_resp";
3495 print STDERR "$msg\n";
3496 Logging::warning($msg,'BrokenDbIntegrity');
3497 return;
3498 }
3499
3500 %auto = %{ $ptrRow };
3501 $self->{dbh}->finish();
3502
3503 #
3504 # forward
3505 #
3506 $sql = "SELECT address FROM resp_forward WHERE rn_id=?";
3507 if ( $self->{dbh}->execute_rownum($sql, $autoId) ) {
3508 my (@list);
3509 while ( $ptrRow = $self->{dbh}->fetchrow() ) {
3510
3511 # skip empty entries - found somewhere @ the wild Net
3512 push @list, $ptrRow->[0] if $ptrRow->[0];
3513 }
3514 if (@list) {
3515 $auto{'redirect'} = join( ',', @list );
3516 }
3517 }
3518 $self->{dbh}->finish();
3519
3520 my @attach;
3521 $sql = "SELECT filename FROM resp_attach WHERE rn_id=?";
3522 if ( $self->{dbh}->execute_rownum($sql, $autoId) ) {
3523 while ( $ptrRow = $self->{dbh}->fetchrow() ) {
3524 push @attach, $ptrRow->[0];
3525 }
3526 }
3527 $self->{dbh}->finish();
3528 $auto{'attach'} = \@attach;
3529 return %auto;
3530}
3531
3532sub makeAddressbookNode {
3533 my ( $self, $mailId, $mailName ) = @_;
3534
3535 my @params;
3536
3537 my $sql = "SELECT Db FROM mysql.db WHERE db='horde'";
3538 unless( $self->{dbh}->execute_rownum($sql) ){
3539 $self->{dbh}->finish();
3540 return;
3541 }
3542 $self->{dbh}->finish();
3543
3544 $sql = "SHOW TABLES FROM horde LIKE 'turba_objects'";
3545 unless( $self->{dbh}->execute_rownum($sql) ) {
3546 $self->{dbh}->finish();
3547 return;
3548 }
3549 $self->{dbh}->finish();
3550
3551 my $ptrHash;
3552 $sql = "SELECT * FROM horde.turba_objects WHERE owner_id = '?'";
3553 if ($self->{dbh}->execute_rownum($sql, $mailName) ) {
3554 while ( $ptrHash = $self->{dbh}->fetchhash() ) {
3555 push @params, $ptrHash;
3556 }
3557 }
3558 $self->{dbh}->finish();
3559
3560 my $ptrRow;
3561 my %turbaVersion = ();
3562 $sql = "SELECT value FROM ServiceNodeEnvironment WHERE section='componentsPackages' AND name = 'psa-turba' AND serviceNodeId=1";
3563 if ($self->{dbh}->execute_rownum($sql)) {
3564 while ( $ptrRow = $self->{dbh}->fetchrow() ) {
3565 # Format version is 2.3.5-cos5.build1011110311.18
3566 if ($ptrRow->[0]=~/(\d+)\.(\d+)\.(\d+)-\S*/) {
3567 $turbaVersion{'majorVersion'} = $1;
3568 $turbaVersion{'minorVersion'} = $2;
3569 $turbaVersion{'patchVersion'} = $3;
3570 }
3571 }
3572 }
3573 $self->{dbh}->finish();
3574
3575 $self->{packer}->setMailAddressbook( $mailId, \@params, \%turbaVersion );
3576}
3577
3578sub getWebspaceId {
3579 my ( $self, $domainId ) = @_;
3580
3581 my $webspace_id;
3582 my $sql = "SELECT webspace_id FROM domains WHERE id = ?";
3583 if ( $self->{dbh}->execute_rownum($sql, $domainId) and my $ptrRow = $self->{dbh}->fetchrow() ) {
3584 $webspace_id = $ptrRow->[0];
3585 }
3586 $self->{dbh}->finish();
3587 return $webspace_id;
3588}
3589
3590sub getDomainWwwRoot {
3591 my ( $self, $domainId, $absolute ) = @_;
3592
3593 my $www_root = DAL::getDomainWwwRoot($domainId);
3594 if($absolute) {
3595 return $www_root;
3596 }
3597 my $parentDomainName;
3598 my $webspace_id = $self->getWebspaceId($domainId);
3599 if($webspace_id) {
3600 $parentDomainName = PleskStructure::getDomainAsciiNameFromId($webspace_id);
3601 }
3602 else {
3603 $parentDomainName = PleskStructure::getDomainAsciiNameFromId($domainId);
3604 }
3605 my $parentDomainRoot = HostingDumper::getWebspaceRoot($parentDomainName, $self->{remoteWebNodes});
3606 $www_root = substr($www_root,length($parentDomainRoot));
3607 substr($www_root,0,1) = '' if substr($www_root,0,1) eq '/' || substr($www_root,0,1) eq '\\';
3608 return $www_root;
3609}
3610
3611sub getDomainCgiRoot {
3612 my ( $self, $domainId, $absolute ) = @_;
3613
3614 my $parentDomainName;
3615 my $webspace_id = $self->getWebspaceId($domainId);
3616 if($webspace_id) {
3617 $parentDomainName = PleskStructure::getDomainAsciiNameFromId($webspace_id);
3618 }
3619 else {
3620 $parentDomainName = PleskStructure::getDomainAsciiNameFromId($domainId);
3621 }
3622 my $parentDomainRoot = HostingDumper::getWebspaceRoot($parentDomainName, $self->{remoteWebNodes});
3623
3624 my $cgi_root;
3625 if( DAL::getDomainCgiBinMode($domainId) eq 'www-root') {
3626 $cgi_root = DAL::getDomainWwwRoot($domainId) . '/cgi-bin';
3627 }
3628 else {
3629 $cgi_root = $parentDomainRoot . '/cgi-bin';
3630 }
3631 if($absolute) {
3632 return $cgi_root;
3633 }
3634 $cgi_root = substr($cgi_root,length($parentDomainRoot));
3635 substr($cgi_root,0,1) = '' if substr($cgi_root,0,1) eq '/';
3636 return $cgi_root;
3637}
3638
3639# Get domain name that could be safely used in Plesk CLI tools
3640# This is a workaround for wildcard subdomains, to be correct display name should be
3641# used instead of name, but there are problems passing it to Plesk CLI tool when there
3642# are no locales installed (easy steps to reproduce such situation - obtain a Debian 6 Virtuozzo box)
3643# and name contains UTF-8 symbols
3644sub getCliDomainName {
3645 my ( $domainName ) = @_;
3646 $domainName =~ s/_/*/;
3647 return $domainName;
3648}
3649
3650my %wwwRootIndex = ();
3651
3652sub makePhostingNode {
3653 my ( $self, $ptrDomain, $ptrDomParams, $ptrSiteApplications, $is_site, $ips, $embeddedInfo ) = @_;
3654
3655 $self->checkProgramTerminated();
3656
3657 Logging::beginObject('hosting',$ptrDomain->{'name'}, undef);
3658 my @SiteApplications = @{$ptrSiteApplications};
3659
3660 unless ( ref($ptrDomain) =~ /HASH/ ) {
3661 Logging::warning("Error: makePhostNode: bad arguments",'assert');
3662 Logging::endObject();
3663 return undef;
3664 }
3665
3666 my (
3667 $domainName, $domainRoot, $path, $sql, $domainServiceDir,
3668 %hosting, $domainId, $xmlName, $fieldName, $id
3669 );
3670 $domainName = $ptrDomain->{'name'};
3671 $domainId = $ptrDomain->{'id'};
3672
3673 my $webspaceId = $self->getWebspaceId($domainId); # used for Site content-related subs
3674 my $webspaceName;
3675
3676 if ($is_site) {
3677 $webspaceName = PleskStructure::getDomainAsciiNameFromId($webspaceId);
3678 if (exists $self->{remoteWebNodes}->{$webspaceName} && defined $self->{remoteWebNodes}->{$webspaceName}) {
3679 $self->{remoteWebNodes}->{$domainName} = $self->{remoteWebNodes}->{$webspaceName};
3680 } else {
3681 $self->{remoteWebNodes}->{$domainName} = undef;
3682 }
3683 }
3684
3685 $self->{packer}->setContentTransport();
3686
3687 my %hostingParams;
3688
3689 %hosting = %{DAL::getHostingParams($domainId)};
3690
3691 if ( defined( $hosting{'webstat'} ) and $hosting{'webstat'} ) {
3692 $hostingParams{'webstat'} = $hosting{'webstat'};
3693 }
3694
3695 if ( defined( $hosting{'ssl'} ) and $hosting{'ssl'} ) {
3696 $hostingParams{'https'} = $hosting{'ssl'};
3697 }
3698
3699 if ( defined( $hosting{'sslRedirect'} ) and $hosting{'sslRedirect'} ) {
3700 $hostingParams{'sslRedirect'} = $hosting{'sslRedirect'};
3701 }
3702
3703 if ( defined( $hosting{'same_ssl'} ) and ( $hosting{'same_ssl'} eq 'true' ) ) {
3704 $hostingParams{'shared-content'} = 'true';
3705 } else {
3706 $hostingParams{'shared-content'} = 'false';
3707 }
3708
3709 my $wwwroot = $self->getDomainWwwRoot($domainId);
3710
3711 if ($wwwroot eq '') {
3712 my $index = $webspaceId == 0 ? $domainId : $webspaceId;
3713 $wwwRootIndex{$index} += 1;
3714 $hostingParams{'www-root'} = "site" . $wwwRootIndex{$index};
3715 } else {
3716 $hostingParams{'www-root'} = $wwwroot;
3717 }
3718
3719 my $domParams = $self->getDomainParams($ptrDomain);
3720 $hostingParams{'errdocs'} = 'true' if ($domParams->{'apacheErrorDocs'} eq 'true');
3721
3722 if (defined $domParams->{'cgi_bin_mode'}) {
3723 $hostingParams{'cgi_bin_mode'} = $domParams->{'cgi_bin_mode'} if ($domParams->{'cgi_bin_mode'} =~ /^old-style$|^www-root$|^webspace$/);
3724 }
3725
3726 my %sysuser;
3727
3728 #
3729 # sysuser
3730 #
3731 Logging::beginObject('sysuser', $domainName, undef);
3732
3733 if ( $id = $hosting{'sys_user_id'} ) {
3734 %sysuser = $self->makePleskSysUserNode($id, $embeddedInfo);
3735 $sysuser{'relative_path'} = HostingDumper::getWebspaceRoot($domainName, $self->{remoteWebNodes});
3736 }
3737
3738 #
3739 # end sysuser
3740 #
3741 Logging::endObject();
3742
3743 my $domUser = lc( $sysuser{'login'} );
3744
3745 my ($phpSettings, $scripting) = HostingDumper::getScripting(\%hosting);
3746
3747 my %phpSettings = %{$phpSettings};
3748
3749 #
3750 # end scripting
3751 #
3752
3753 $hostingParams{'wu_script'} = 'true' if exists $ptrDomParams->{'wu_script'} && $ptrDomParams->{'wu_script'} eq 'true';
3754
3755 $hostingParams{'sitebuilder-site-id'} = $ptrDomParams->{'site_builder_site_id'} if exists $ptrDomParams->{'site_builder_site_id'};
3756
3757 my $published = $self->{packer}->getSb5SitePublished(getCliDomainName($domainName));
3758 $hostingParams{'sitebuilder-site-published'} = $published if defined $published;
3759
3760 my @sites = @{ DAL::getSitesByWebspaceId($domainId) };
3761
3762 my $pk = $self->getDomainCertificatePrivateKey($hosting{'certificate_id'}, $domainId);
3763 if ($pk) {
3764 $hostingParams{'certificate_ref'} = $self->getCertificateRef($pk);
3765 }
3766
3767 $domainRoot = HostingDumper::getDomainRoot($domainName, $self->{remoteWebNodes});
3768 my $webspaceRoot = $webspaceName ? HostingDumper::getDomainRoot($webspaceName, $self->{remoteWebNodes}) : $domainRoot;
3769 $domainServiceDir = HostingDumper::getSystemDomainRoot($domainName, $self->{remoteWebNodes});
3770
3771 if ('true' eq $self->{packer}->getContentTransport()->hasLink("$domainRoot/conf", "$domainServiceDir/conf")) {
3772 $hostingParams{'original-conf-directory'} = "$domainRoot/conf/";
3773 } elsif (defined($ptrDomain->{'parentDomainName'})) {
3774 my ($subDomainDirName) = $domainName =~ /([^.]+)/;
3775 my $parentDomainRoot = HostingDumper::getDomainRoot($ptrDomain->{'parentDomainName'}, $self->{remoteWebNodes});
3776 if ('true' eq $self->{packer}->getContentTransport()->hasLink("$parentDomainRoot/subdomains/$subDomainDirName/conf", "$domainServiceDir/conf")) {
3777 $hostingParams{'original-conf-directory'} = "$parentDomainRoot/subdomains/$subDomainDirName/conf/";
3778 } else {
3779 $hostingParams{'original-conf-directory'} = "$domainServiceDir/conf/";
3780 }
3781 } else {
3782 $hostingParams{'original-conf-directory'} = "$domainServiceDir/conf/";
3783 }
3784
3785 if ( !$self->{only_mail_dump} ) {
3786 if (exists $domParams->{'phpSettingsId'}) {
3787 %phpSettings = %{DAL::getPhpSettings($domParams->{'phpSettingsId'})};
3788 my $phpSettingsCustom = DAL::getPhpSettingsCustom($domParams->{'phpSettingsId'});
3789 $phpSettings{'notice'} = $phpSettingsCustom if defined $phpSettingsCustom;
3790 }
3791
3792 $self->{packer}->setDomainPhosting( $domainId,
3793 \%hostingParams,
3794 $is_site? undef: \%sysuser,
3795 $scripting,
3796 $ips,
3797 \%phpSettings
3798 );
3799
3800 if (defined($embeddedInfo->{'web-settings'})) {
3801 foreach my $webSettings (@{$embeddedInfo->{'web-settings'}}) {
3802 if (ref($webSettings) =~ /HASH/ && $webSettings->{'vhost-name'} eq $domainName) {
3803 eval {require XML::Simple; 1;};
3804 my $xs = XML::Simple->new(ForceArray => 1);
3805 my $webSettingsXml = $xs->XMLout($webSettings, RootName => 'web-settings');
3806 $webSettingsXml = Encode::encode('UTF-8', $webSettingsXml); # workaround for UTF8 symbols
3807 $self->{packer}->appendNodeToPhosting($domainId, $webSettingsXml);
3808 }
3809 }
3810 }
3811
3812 }
3813 else {
3814 if( @sites ) {
3815 $self->{packer}->setDomainPhostingEmpty( $domainId, $is_site? undef: \%sysuser, $ips );
3816 }
3817 }
3818
3819 if ( !$self->{only_mail_dump} ) {
3820 #-----------------------------------------------------------------
3821 # Site applications content should not be included into dump
3822 # together with other website content.
3823 #-----------------------------------------------------------------
3824 my @exclude_httpdocs_files;
3825 push @exclude_httpdocs_files, 'plesk-stat';
3826 my @exclude_httpsdocs_files;
3827 push @exclude_httpsdocs_files, 'plesk-stat';
3828 my @exclude_cgi_bin_files;
3829 foreach my $sapp (@SiteApplications) {
3830 next if !$sapp->isDomainSiteapp($ptrDomain->{'displayName'});
3831
3832 if ( $sapp->isSsl() ) {
3833 push @exclude_httpsdocs_files, $sapp->getHtdocsFiles();
3834 }
3835 else {
3836 push @exclude_httpdocs_files, $sapp->getHtdocsFiles();
3837 }
3838 push @exclude_cgi_bin_files, $sapp->getCgibinFiles();
3839 }
3840
3841 # Hosting content dump
3842
3843 if (!$self->{configuration_dump} ) {
3844 my @exclude_vhost_files;
3845 my $httpdocsDir = $self->getDomainWwwRoot($domainId);
3846 push @exclude_vhost_files, "$httpdocsDir/plesk-stat";
3847
3848 push @exclude_vhost_files, "httpsdocs/plesk-stat";
3849
3850 if(@sites) {
3851 foreach my $ptrHash (@sites) {
3852 my $siteHttpdocsDir = $self->getDomainWwwRoot($ptrHash->{'id'});
3853 push @exclude_vhost_files, "$siteHttpdocsDir/plesk-stat";
3854
3855 # Fix to dump subdomains content, which became sites after upgrade to 11.5 and some its content unavailable for sysuser
3856 # http://plesk-process.parallels.com/TargetProcess2/Project/QA/Bug/View.aspx?BugID=141214
3857 # Exclude conf directory, because its content must be moved to system directory on upgrade and exclude error_docs, because it does not used
3858 my $subdomainName = $ptrHash->{'name'};
3859 $subdomainName =~ s/\.$ptrDomain->{'name'}//g;
3860 my $subdomainDataDir = "subdomains/$subdomainName";
3861 push @exclude_vhost_files, "$subdomainDataDir/conf" if (-d "$domainRoot/$subdomainDataDir/conf");
3862 push @exclude_vhost_files, "$subdomainDataDir/error_docs" if (-d "$domainRoot/$subdomainDataDir/error_docs");
3863 }
3864 }
3865 push(@exclude_vhost_files, 'logs');
3866 if (%sysuser && ($sysuser{'shell'} eq AgentConfig::getChrootShell() || ref($sysuser{'scheduled-tasks'}) =~ /HASH/)) {
3867 # chroot dirs:
3868 push(@exclude_vhost_files, 'bin', 'sbin', 'dev', 'lib', 'lib64', 'usr', 'libexec', 'etc', 'tmp', 'var');
3869 }
3870
3871 my $options = {
3872 'sysuser' => $domUser
3873 , 'include' => $self->{includeFiles}
3874 , 'exclude' => \@exclude_vhost_files
3875 };
3876 if (!$is_site && $self->{dump_vhost}) {
3877 $self->{packer}->setDomainUserDataContent( $domainId, $domainName, $domainRoot, $options);
3878 } elsif (!$is_site) {
3879 $self->{packer}->setDomainPhostingFullContent($domainId, $domainName, $domainRoot, $options);
3880 }
3881 }
3882
3883 if ( !$self->{configuration_dump} ) {
3884 if ($self->{dump_vhost}) {
3885 $self->{packer}->setDomainPhostingStatisticsContent( $domainId, $domainName, "$domainServiceDir/statistics", {} );
3886 } else {
3887 my $webstatRoot = $domainServiceDir . "/statistics/webstat";
3888 $self->{packer}->setDomainPhostingWebstatContent( $domainId, $domainName, $webstatRoot );
3889 $self->{packer}->setDomainPhostingWebstatSslContent( $domainId, $domainName, "$domainServiceDir/statistics/webstat-ssl" );
3890 $self->{packer}->setDomainPhostingFtpstatContent( $domainId, $domainName, "$domainServiceDir/statistics/ftpstat" );
3891 $self->{packer}->setDomainPhostingAnonFtpstatContent( $domainId, $domainName, "$domainServiceDir/statistics/anon_ftpstat" );
3892 }
3893
3894 $self->{packer}->setDomainPhostingProtectedDirContent( $domainId, $domainName, "$domainServiceDir/pd" );
3895 $self->{packer}->setDomainPhostingLogsContent( $domainId, $domainName, "$domainServiceDir/logs" );
3896 }
3897
3898 if ( !$self->{configuration_dump} && !$self->{only_mail_dump} ) {
3899 $self->addSb5DomainContent( $domainId, $domainName, $ptrDomParams->{'site_builder_site_id'});
3900 }
3901 else {
3902 Logging::debug("Skip domain sitebuilder content dumping due to settings");
3903 }
3904
3905 #-----------------------------------------------------------------
3906 # Dump of installed site applications
3907 #-----------------------------------------------------------------
3908 foreach my $sapp (@SiteApplications) {
3909 if ( !$sapp->isDomainSiteapp($ptrDomain->{'displayName'}) ) {
3910 next;
3911 }
3912 $self->dumpSiteApplication( $sapp, $domainId, 'domain', $webspaceId? $webspaceId:$domainId, $embeddedInfo);
3913 }
3914
3915 $self->makeDomainLogrotationNode($domainId);
3916 $self->addAnonFtp( $domainId, $domainName, { 'sysuser' => $domUser } );
3917 #
3918 # protected dirs
3919 #
3920 $sql = "SELECT id, path, realm, non_ssl, cgi_bin, `ssl` FROM protected_dirs WHERE dom_id=? ORDER BY id";
3921 if ( $self->{dbh}->execute_rownum($sql, $domainId) ) {
3922 my (@dirs);
3923 while ( my $ptrRow = $self->{dbh}->fetchrow() ) {
3924 push @dirs, [ @{$ptrRow} ];
3925 }
3926 foreach my $ptrRow (@dirs) {
3927 my $pdirId = $ptrRow->[0];
3928 my $pdirPath = $ptrRow->[1];
3929 my $pdirTitle = $ptrRow->[2];
3930 my $pdirNonSSL = $ptrRow->[3];
3931 my $pdirCGI = $ptrRow->[4];
3932 my $pdirSSL = $ptrRow->[5];
3933 $self->makeProtDirNode( $domainId, $pdirId, $pdirPath, $pdirTitle, $pdirNonSSL, $pdirSSL, $pdirCGI);
3934 }
3935 }
3936 $self->{dbh}->finish();
3937 #
3938 # end protected dirs
3939 #
3940
3941 unless ($is_site) {
3942 #
3943 # web users
3944 #
3945 my $webs = DAL::getWebUsers($domainId);
3946
3947 foreach my $ptrHash (@{$webs}) {
3948 $self->makeWebUserNode( $ptrHash, $domainId, $domainName );
3949 }
3950 #
3951 # end web users
3952 #
3953 }
3954
3955 unless ($is_site) {
3956 #
3957 # ftpusers
3958 #
3959 my $ftps = DAL::getAdditionalFtpUsers($domainId);
3960 foreach my $ptrHash (@{$ftps}) {
3961 $self->makeSubFtpUserNode( $ptrHash, $domainId, $domainName );
3962 }
3963 #
3964 # end ftpusers
3965 #
3966 }
3967
3968 #
3969 # subdomains
3970 #
3971
3972 $self->{packer}->setEmptySubFtpUsersNode($domainId);
3973 $self->{packer}->removePhostingChildNodeIfEmpty( $domainId, 'subdomain' );
3974 $self->{packer}->removePhostingChildNodeIfEmpty( $domainId, 'ftpuser' );
3975
3976 #
3977 # end subdomains
3978 #
3979 }
3980
3981 if( @sites ) {
3982 foreach my $ptrHash ( @sites ) {
3983 eval {
3984 $self->makeSiteNode( $ptrHash->{'name'}, $ptrHash->{'displayName'}, \@SiteApplications, $embeddedInfo );
3985 1;
3986 } or do {
3987 $self->checkProgramTerminated();
3988 $self->excludeProblemSiteFromBackup( $domainId, $ptrHash, $@ );
3989 }
3990 }
3991 $self->{packer}->removePhostingChildNodeIfEmpty( $domainId, 'site' );
3992 }
3993
3994 if ( !$self->{only_mail_dump} ) {
3995 #
3996 # configuration files (conf/vhost[_ssl].conf)
3997 #
3998 my $confDir = "$domainServiceDir/conf/";
3999 my @excludeConfFiles;
4000 push(@excludeConfFiles, 'httpd.include', 'last_httpd.include', 'last_httpd.conf', '*.*_httpd.include', '*.*_httpd.conf');
4001 push(@excludeConfFiles, 'last_nginx.conf', '*.*_nginx.conf', 'nginx.conf');
4002 push(@excludeConfFiles, 'siteapp.d', 'stat_ttl.conf', 'webalizer.conf', 'prev_month.found');
4003 Logging::debug('Exclude conf files: ' . join(", ", @excludeConfFiles));
4004 $self->{packer}->setDomainPhostingConfContent( $domainId, $domainName, $confDir, { 'exclude' => \@excludeConfFiles } );
4005 #
4006 # end configuration files (conf/vhost[_ssl].conf)
4007 #
4008
4009 #
4010 # Webalizer configuration
4011 #
4012 my ( $directRef, @hiddenRefs, @groupRefs );
4013
4014 my $sql = "SELECT referrer FROM webalizer_hidden_referrer "
4015 . " WHERE dom_id=?";
4016 if ( $self->{dbh}->execute_rownum($sql, $domainId) ) {
4017 while ( my $ptrRow = $self->{dbh}->fetchrow() ) {
4018 if ( $ptrRow->[0] eq "Direct Request" ) {
4019 $directRef = 'true';
4020 }
4021 else {
4022 push @hiddenRefs, $ptrRow->[0];
4023 }
4024 }
4025 }
4026 $self->{dbh}->finish();
4027
4028 $sql = "SELECT referrer, group_name FROM webalizer_group_referrer "
4029 . " WHERE dom_id=?";
4030 if ( $self->{dbh}->execute_rownum($sql, $domainId) ) {
4031 while ( my $ptrRow = $self->{dbh}->fetchrow() ) {
4032 push @groupRefs, { 'ref' => $ptrRow->[0], 'name' => $ptrRow->[1] };
4033 }
4034 }
4035 $self->{dbh}->finish();
4036
4037 $self->{packer}->setDomainWebalizer( $domainId, $directRef, \@hiddenRefs, \@groupRefs );
4038
4039 #
4040 # Perfomance
4041 #
4042 if ( ( defined( $hosting{'max_connection'} ) and $hosting{'max_connection'} )
4043 or ( defined( $hosting{'traffic_bandwidth'} ) and $hosting{'traffic_bandwidth'} )
4044 ) {
4045 $self->{packer}->setDomainPerfomance( $domainId,
4046 $hosting{'max_connection'},
4047 $hosting{'traffic_bandwidth'} );
4048 }
4049
4050 if( exists $ptrDomParams->{'stat_ttl'} ){
4051 $self->{packer}->setDomainWebStat( $domainId, $ptrDomParams->{'stat_ttl'} );
4052 }
4053
4054 }
4055
4056 Logging::endObject();
4057}
4058
4059sub dumpSiteApplication {
4060 my ( $self, $sapp, $parent, $parentType, $webspaceId, $embeddedInfo ) = @_;
4061
4062 my $sapp_id = $parentType . "_" . $parent . "_" . $sapp->getInstallPrefix();
4063
4064 my $prefix = $sapp->getInstallPrefix();
4065
4066 my $licenseType = $sapp->getAPSClientItemLicenseType();
4067
4068 if ( 'domain' eq $parentType ) {
4069 $self->{packer}->addDomainSapp(
4070 $parent, $sapp_id, $sapp, $licenseType
4071 );
4072 }
4073 elsif ( 'subdomain' eq $parentType ) {
4074 $self->{packer}->addSubDomainSapp(
4075 $parent, $sapp_id, $sapp, $licenseType
4076 );
4077 }
4078 else {
4079 Logging::warning(
4080 "Error: dumpSiteApplication: Unexpected type of parent \"$parentType\"",'assert');
4081 }
4082
4083 $self->{packer}->setSappParams( $sapp_id, $sapp );
4084
4085
4086 #-----------------------------------------------------------------
4087 # Linked resources
4088 #-----------------------------------------------------------------
4089
4090 # Databases
4091 foreach my $row ( $sapp->getDatabases() ) {
4092 $self->makeDatabaseNode( $row->{'id'}, $parent, $parentType, $sapp_id, $row, $embeddedInfo );
4093 }
4094
4095 # Custom buttons
4096 foreach my $row ( $sapp->getCustomButtons() ) {
4097 $self->getCustomButtonById71( $row->{'id'}, $parent, $parentType, $sapp_id );
4098 }
4099
4100 my $installDirApsRegistryId = undef;
4101 $installDirApsRegistryId = $sapp->getInstallDirApsRegistryId();
4102 $self->{packer}->makeSiteAppInstalled( $sapp_id, $prefix, $sapp->isSsl(), $installDirApsRegistryId );
4103 $self->{packer}->setSappEntryPoints( $sapp_id, $sapp );
4104 $self->{packer}->setSappApsControllerInfo( $sapp_id, $sapp );
4105
4106 # backupArchive
4107
4108 my $backupArchiveFile = $sapp->getBackupArchiveFile();
4109 unless ( open( BAFILE, "<$backupArchiveFile" ) ) {
4110 Logging::warning("Error: unable to open BackupArchive from APS controller:" . $backupArchiveFile);
4111 }
4112 my $backupArchiveContent;
4113 while(<BAFILE>) {
4114 $backupArchiveContent .= $_;
4115 }
4116 close(BAFILE);
4117 unlink($backupArchiveFile);
4118
4119 $self->{packer}->setSappApscNode($sapp_id, $backupArchiveContent);
4120 $self->{packer}->setSappApsLicense($sapp_id, $sapp);
4121 $self->{packer}->setSappSettings($sapp_id, $sapp);
4122
4123 my $apsResourceId = $sapp->getApplicationApsResourceId();
4124}
4125
4126sub makeDomainLogrotationNode {
4127 my ( $self, $domainId ) = @_;
4128
4129 my $logrotation_id = DAL::getDomainParam($domainId, 'logrotation_id');
4130 if ( defined $logrotation_id ) {
4131 $self->{packer}->setDomainLogrotation( $domainId, DAL::getLogrotation($logrotation_id) );
4132 }
4133}
4134
4135sub makeWebUserNode {
4136 my ( $self, $ptrWebUser, $domainId, $domainName ) = @_;
4137 unless ( ref($ptrWebUser) =~ /HASH/ ) {
4138 Logging::warning("Error: makeWebUserNode: bad argumets", 'assert');
4139 return;
4140 }
4141 my ( $home, $userName, $item, $xmlName, $fieldName );
4142
4143 my %sysuser;
4144
4145 %sysuser = $self->makePleskSysUserNode( $ptrWebUser->{'sys_user_id'} );
4146 $userName = $sysuser{'login'};
4147
4148 my $domainRoot = HostingDumper::getDomainRoot($domainName, $self->{remoteWebNodes});
4149
4150 my $webUserHome = $domainRoot . "/web_users/$userName";
4151 my $privateData = $domainRoot . "/private/$userName";
4152
4153 $self->{packer}->addDomainWebUser(
4154 $domainId, $domainName, \%sysuser,
4155 $ptrWebUser, $webUserHome, $privateData
4156 );
4157}
4158
4159#
4160# makeSubFtpUserNode - make node for additionals ftp accounts
4161#
4162
4163sub makeSubFtpUserNode {
4164 my ( $self, $ptrFtpUser, $domainId, $domainName ) = @_;
4165
4166 my %sysuser = $self->makePleskSysUserNode($ptrFtpUser->{'sys_user_id'});
4167
4168 $sysuser{'relative_path'} = HostingDumper::getWebspaceRoot($domainName, $self->{remoteWebNodes});
4169
4170 $self->{packer}->addDomainSubFtpUser($domainId, $domainName, \%sysuser, $ptrFtpUser);
4171}
4172
4173sub makeProtDirNode {
4174 my ( $self, $domainId, $pdirId, $pdirPath, $pdirTitle, $pdirNonSSL, $pdirSSL, $pdirCGI ) = @_;
4175
4176 my ( $sql, $item, $ptrRow );
4177
4178 # workaround of CLI inabliity to create '' directory.
4179 if ( $pdirPath eq '' ) {
4180 $pdirPath = '/';
4181 }
4182
4183 $sql = "SELECT p.login, a.password, a.type FROM pd_users p "
4184 . " LEFT JOIN accounts a ON p.account_id = a.id "
4185 . " WHERE p.pd_id=? ORDER BY p.id";
4186
4187 my @users;
4188 if ( $self->{dbh}->execute_rownum($sql, $pdirId) ) {
4189 while ( $ptrRow = $self->{dbh}->fetchrow() ) {
4190 push @users,
4191 {
4192 'login' => $ptrRow->[0],
4193 'passwd' => $ptrRow->[1],
4194 'passwdType' => $ptrRow->[2]
4195 };
4196 }
4197 }
4198 $self->{dbh}->finish();
4199 $self->{packer}->addDomainProtectedDir( $domainId, $pdirPath, $pdirTitle, $pdirNonSSL, $pdirSSL, $pdirCGI, \@users );
4200}
4201
4202sub addAnonFtp {
4203 my ( $self, $domainId, $domainName, $optPtr ) = @_;
4204
4205 my ( $ptrHash, $count, $domainRoot, $sql );
4206 $count = 0;
4207 $sql = "SELECT * FROM anon_ftp WHERE dom_id=?";
4208 if ( $self->{dbh}->execute_rownum($sql, $domainId) ) {
4209 while ( $ptrHash = $self->{dbh}->fetchhash() ) {
4210 $domainRoot = HostingDumper::getDomainRoot($domainName, $self->{remoteWebNodes});
4211 my ( $pub_path, $incoming_path );
4212
4213 $pub_path = "$domainRoot/anon_ftp/pub";
4214 $incoming_path = "$domainRoot/anon_ftp/incoming";
4215
4216 $self->{packer}->setDomainAnonFtp( $domainId, $domainName, $ptrHash, $pub_path, $incoming_path, $optPtr );
4217
4218 $count++;
4219 }
4220 }
4221 $self->{dbh}->finish();
4222 return $count;
4223}
4224
4225sub addSb5DomainContent {
4226 my ( $self, $domainId, $domainName, $uuid ) = @_;
4227 unless ( defined $uuid) {
4228 Logging::debug( "addSb5DomainContent: domain $domainName site_builder_site_id is not found. skip");
4229 return;
4230 }
4231 $self->{packer}->setSb5DomainContent( $domainId, $domainName, $uuid);
4232}
4233
4234sub makePleskSysUserNode {
4235 my ( $self, $sysUserId, $embeddedInfo ) = @_;
4236 my %sysuser = %{ HostingDumper::getSysUserInfo($sysUserId) };
4237
4238 Logging::trace("Making system user node: $sysuser{'login'}");
4239
4240 my $sysUserInfo = undef;
4241 if (defined($embeddedInfo->{sysuser})) {
4242 $sysUserInfo = (grep { $_->{name} eq $sysuser{login} } @{$embeddedInfo->{sysuser}})[0];
4243 }
4244
4245 if ( $sysuser{'account_id'} != 0 ) {
4246 ( $sysuser{'passwd'}, $sysuser{'passwdType'} ) = $self->makeAccountPasswordNode( $sysuser{'account_id'} );
4247 }
4248
4249 if (defined($sysUserInfo) && defined($sysUserInfo->{'scheduled-tasks'})) {
4250 my $scheduledTasks = $sysUserInfo->{'scheduled-tasks'}->[0];
4251 if (ref($scheduledTasks) =~ /HASH/ && defined($scheduledTasks->{'failure'})) {
4252 my $message = $scheduledTasks->{'failure'}[0]->{'message'}[0];
4253 Logging::warning($message);
4254 } else {
4255 $sysuser{'scheduled-tasks'} = $scheduledTasks;
4256 }
4257 }
4258
4259 return %sysuser;
4260}
4261
4262sub getCron {
4263 my ( $self, $account ) = @_;
4264
4265 my $crontabmng = AgentConfig::get("PRODUCT_ROOT_D") . "/admin/sbin/crontabmng";
4266 if ( -x $crontabmng ) {
4267 open( CRONTAB, "$crontabmng get $account |" );
4268 my $crontab = "";
4269 while (<CRONTAB>) {
4270 last if $_ eq "0\n";
4271 $crontab .= $_;
4272 }
4273 close(CRONTAB);
4274 if ( $crontab ne "\n" ) {
4275 return $crontab;
4276 }
4277 }
4278}
4279
4280sub makeSyntheticSysUserNode {
4281 my ( $self, $name, $password, $passtype ) = @_;
4282
4283 my %sysuser;
4284 $sysuser{'login'} = $name;
4285 $sysuser{'passwd'} = $password;
4286 $sysuser{'passwdType'} = $passtype;
4287 return %sysuser;
4288}
4289
4290sub makeFhostingNode {
4291 my ( $self, $ptrDomain, $ips ) = @_;
4292
4293 return if ( $self->{only_mail_dump} );
4294
4295 unless ( ref($ptrDomain) =~ /HASH/ ) {
4296 Logging::warning("Error: makeFhostingNode: bag arguments", 'assert');
4297 return;
4298 }
4299 my ( $sql, $domainId, $forward, $rowPtr );
4300 $domainId = $ptrDomain->{'id'};
4301 $sql = "SELECT redirect FROM forwarding WHERE dom_id=?";
4302 unless ( ( $self->{dbh}->execute_rownum($sql, $domainId) ) && ( $rowPtr = $self->{dbh}->fetchrow() ) ) {
4303 $self->{dbh}->finish();
4304 my $msg = "Broken referencial integrity: forward for domain " . $ptrDomain->{'name'} . " is not found in forwarding";
4305 print STDERR "$msg\n";
4306 Logging::warning($msg,'BrokenDbIntegrity');
4307 return;
4308 }
4309
4310 ($forward) = @{ $rowPtr };
4311 $self->{packer}->setDomainFhosting( $domainId, $forward, $ips);
4312 $self->{dbh}->finish();
4313}
4314
4315sub makeShostingNode {
4316 my ( $self, $ptrDomain, $ips ) = @_;
4317
4318 return if ( $self->{only_mail_dump} );
4319
4320 unless ( ref($ptrDomain) =~ /HASH/ ) {
4321 Logging::warning("Error: makeShostingNode: bag arguments", 'assert');
4322 return;
4323 }
4324
4325 my ( $sql, $domainId, %forward, $hashPtr );
4326 $domainId = $ptrDomain->{'id'};
4327
4328 $sql = "SELECT * FROM forwarding WHERE dom_id=?";
4329 unless ( ( $self->{dbh}->execute_rownum($sql, $domainId) ) && ( $hashPtr = $self->{dbh}->fetchhash() ) ) {
4330 $self->{dbh}->finish();
4331 my $msg = "Broken referencial integrity: forward for domain " . $ptrDomain->{'name'} . " is not found in forwarding";
4332 print STDERR "$msg\n";
4333 Logging::warning($msg,'BrokenDbIntegrity');
4334 return;
4335 }
4336
4337 $self->{dbh}->finish();
4338
4339 %forward = %{ $hashPtr };
4340 $self->{packer}->setDomainShosting( $domainId, \%forward, $ips );
4341 $self->{dbh}->finish();
4342}
4343
4344sub _makePasswordData{
4345 my ($password, $type) = @_;
4346
4347 if (!defined $password) {
4348 Logging::warning( "'undef' password passed to _makePasswordData. Change to empty!" );
4349 $password = '';
4350 }
4351
4352 if (!$password) {
4353 $type = 'plain';
4354 }
4355 return ($password, $type);
4356}
4357
4358my $tableAccounts = undef;
4359
4360sub makeAccountPasswordNode {
4361 my ( $self, $accountId ) = @_;
4362
4363 my ( $passwd, $type );
4364 my %values;
4365
4366 if( not defined $tableAccounts ){
4367 if ( $self->{dbh}->execute( "SELECT id, password, type FROM accounts" ) ) {
4368 while( my $ptrRow = $self->{dbh}->fetchrow() ){
4369 $values{$ptrRow->[0]} = ();
4370 push @{$values{$ptrRow->[0]}}, $ptrRow->[1];
4371 push @{$values{$ptrRow->[0]}}, $ptrRow->[2];
4372 }
4373 }
4374 $self->{dbh}->finish();
4375 $tableAccounts = \%values;
4376 }
4377
4378 if ( exists $tableAccounts->{$accountId} )
4379 {
4380 ( $passwd, $type ) = @{$tableAccounts->{$accountId}};
4381 ( $passwd, $type ) = _makePasswordData( $passwd, CommonPacker::normalizePasswordType($type) );
4382 }
4383 else {
4384
4385 # generates a stub node
4386 ( $passwd, $type ) = _makePasswordData();
4387 }
4388 $self->{dbh}->finish();
4389
4390 return ( $passwd, $type );
4391}
4392
4393my @_planItemNames;
4394
4395sub getPlanItemNames {
4396 my ( $self ) = @_;
4397
4398 if ( @_planItemNames ) {
4399 return \@_planItemNames;
4400 }
4401
4402 my $planItemsPtr = DAL::getPlanItems();
4403 foreach my $planItemPtr ( @{$planItemsPtr} ) {
4404 push @_planItemNames, $planItemPtr->{'name'};
4405 }
4406
4407 return \@_planItemNames;
4408}
4409
4410sub getSubscriptionProperties {
4411 my ( $self, $type, $id ) = @_;
4412
4413 my @planItemNames = @{$self->getPlanItemNames()};
4414
4415 my $subscriptionProperties = $self->getSubscriptionPropertiesHash($id, $type);
4416
4417 foreach my $key (keys %{$subscriptionProperties}) {
4418 if ( grep $_ eq $key, @planItemNames) {
4419 my $templatePlanItemNode = $self->{packer}->makeTemplatePlanItem( $key, $subscriptionProperties->{$key} );
4420 $self->{packer}->addToPreferences('domain', $id, $templatePlanItemNode) if defined $templatePlanItemNode;
4421 }
4422 }
4423}
4424
4425sub getSubscriptionPropertiesHash {
4426 my ( $self, $id, $type ) = @_;
4427
4428 my %subscriptionProperties;
4429
4430 my $sql = "SELECT name, value FROM SubscriptionProperties INNER JOIN Subscriptions ON id=subscription_id WHERE object_id=? AND object_type='?'";
4431 if ( $self->{dbh}->execute_rownum($sql, $id, $type) ) {
4432 while ( my $ptrHash = $self->{dbh}->fetchhash() ) {
4433 $subscriptionProperties{$ptrHash->{'name'}} = $ptrHash->{'value'};
4434 }
4435 }
4436 $self->{dbh}->finish();
4437
4438 return \%subscriptionProperties;
4439}
4440
4441sub getSubscription {
4442 my ( $self, $type, $id) = @_;
4443 my $subscriptionNode = $self->makeSubscriptionNode($type, $id);
4444 $self->{packer}->addToPreferences($type, $id, $subscriptionNode) if defined $subscriptionNode;
4445 return $subscriptionNode;
4446}
4447
4448sub makeSubscriptionNode {
4449 my ( $self, $type, $id ) = @_;
4450
4451 my $rowPtr = DAL::getSubscription($type, $id);
4452 if ( !defined($rowPtr) ) {
4453 $self->{dbh}->finish();
4454 return $self->{packer}->makeSubscriptionNode(undef, undef, undef); # subscription node is needed for dump subscription properties
4455 }
4456 my $subscription_id = $rowPtr->{'id'};
4457 my $locked = $rowPtr->{'locked'};
4458 my $synchronized = defined$rowPtr->{'synchronized'} ? $rowPtr->{'synchronized'} : undef;
4459 my $custom = defined $rowPtr->{'custom'} ? $rowPtr->{'custom'} : undef;
4460 my $externalId = defined $rowPtr->{'external_id'} ? $rowPtr->{'external_id'} : undef;
4461
4462 $self->{dbh}->finish();
4463
4464 my $subscriptionNode = $self->{packer}->makeSubscriptionNode($locked, $synchronized, $custom, $externalId);
4465
4466 my %planQuantity;
4467 my $sql = "SELECT plan_id, quantity FROM PlansSubscriptions WHERE subscription_id = ?";
4468 if ( $self->{dbh}->execute_rownum($sql, $subscription_id) ) {
4469 while ( my $row = $self->{dbh}->fetchrow() ) {
4470 $planQuantity{$row->[0]} = $row->[1];
4471 }
4472 }
4473 $self->{dbh}->finish();
4474
4475 while ( my ($planId, $quantity) = each(%planQuantity) ) {
4476 $sql = "SELECT type, uuid FROM Templates WHERE id = ?";
4477 unless ( $self->{dbh}->execute_rownum($sql, $planId) ) {
4478 Logging::warning( "Error during getting uuid from plan '$planId'");
4479 $self->{dbh}->finish();
4480 next;
4481 }
4482 if ( my $row = $self->{dbh}->fetchrow() ) {
4483 my ($planType, $planGuid) = @$row;
4484 my $is_addon;
4485 if ($planType eq 'domain_addon') {
4486 $is_addon = 'true';
4487 }
4488 $self->{packer}->addSubscriptionPlan($subscriptionNode, $quantity, $planGuid, $is_addon);
4489 }
4490 $self->{dbh}->finish();
4491 }
4492
4493 return $subscriptionNode;
4494}
4495
4496sub makeSpamassassinNode {
4497 my ( $self, $mailId, $mailNm, $domainAsciiname, $status, $dir ) = @_;
4498
4499 my $mailname = $mailNm . '@' . $domainAsciiname;
4500
4501 my $is_server = $mailname eq '*@*';
4502
4503 my $spamFilter = DAL::getMailnameSpamfilter($mailname);
4504 unless ( exists $spamFilter->{'id'} ) {
4505 Logging::debug( "Unable get information about spam filter for $mailname");
4506 return;
4507 }
4508
4509 my ( @blacckList, @whiteList, @unblackList, @unwhiteList, $action, $requiredScore, $subj_text );
4510
4511 my $filter_id = $spamFilter->{'id'};
4512 if ( exists $spamFilter->{'reject_spam'} ) {
4513 $action = ( $spamFilter->{'reject_spam'} eq 'true') ? 'delete' : 'mark';
4514 }
4515
4516 my $spamFilterPreferences = DAL::getSpamfilterPreferences($filter_id);
4517 unless ( $is_server || scalar(@$spamFilterPreferences) ) {
4518 $filter_id = DAL::getServerSpamfilterId();
4519 $spamFilterPreferences = DAL::getSpamfilterPreferences($filter_id) if defined $filter_id;
4520 }
4521
4522 if(@$spamFilterPreferences) {
4523 foreach my $row (@$spamFilterPreferences) {
4524 if ($row->[0] eq "blacklist_from") {
4525 push @blacckList, $row->[1];
4526 }
4527 elsif ($row->[0] eq "whitelist_from") {
4528 push @whiteList, $row->[1];
4529 }
4530 elsif ($row->[0] eq "unblacklist_from") {
4531 push @unblackList, $row->[1];
4532 }
4533 elsif ($row->[0] eq "unwhitelist_from") {
4534 push @unwhiteList, $row->[1];
4535 }
4536 elsif ($row->[0] eq "required_score") {
4537 $requiredScore = $row->[1];
4538 }
4539 elsif ($row->[0] eq "rewrite_header") {
4540 $row->[1] =~ s/^subject //;
4541 $subj_text = $row->[1];
4542 }
4543 elsif ($row->[0] eq "action") {
4544 if ($row->[1] ne 'delete' && $row->[1] ne 'move') {
4545 $action = 'mark';
4546 } else {
4547 $action = $row->[1];
4548 }
4549 }
4550 }
4551 }
4552
4553 my $spamServerSettings;
4554 if ($is_server) {
4555 $spamServerSettings = DAL::getSpamServerSettings();
4556 $status = $spamServerSettings->{'spamfilter_enabled'} if exists $spamServerSettings->{'spamfilter_enabled'};
4557 }
4558
4559 $self->{packer}->setMailSpamSettings(
4560 $mailId, $mailNm, $domainAsciiname,
4561 ( $status eq 'true' ? 'on' : 'off' ),
4562 undef, $action,
4563 $requiredScore, undef, $subj_text,
4564 \@blacckList, \@whiteList,
4565 \@unblackList, \@unwhiteList,
4566 $dir, (keys(%$spamServerSettings)? $spamServerSettings : undef)
4567 );
4568}
4569
4570sub getCustomButtonById71 {
4571 my ( $self, $id, $parent, $parentType, $sappId ) = @_;
4572
4573 my $options;
4574
4575 # several times there was empty button place in database, which is incorrect
4576 my $sql = "SELECT * FROM custom_buttons WHERE id=? AND place!=''";
4577 unless ( ( $self->{dbh}->execute_rownum($sql, $id) ) && ( $options = $self->{dbh}->fetchhash() ) ) {
4578 $self->{dbh}->finish();
4579 return;
4580 }
4581 $self->{dbh}->finish();
4582
4583
4584 my $customButtonsDir = AgentConfig::get("PRODUCT_ROOT_D") . '/admin/htdocs/images/custom_buttons';
4585
4586 my $icon = $options->{'file'};
4587
4588 if( $sappId ){
4589 if ( 'domain' eq $parentType ) {
4590 $self->{packer}->addDomainSappCustomButton( $parent, $sappId, $id, $options, $customButtonsDir, $icon );
4591 }
4592 elsif ( 'subdomain' eq $parentType ) {
4593 $self->{packer}->addSubDomainSappCustomButton( $parent, $sappId, $id, $options, $customButtonsDir, $icon );
4594 }
4595 else {
4596 Logging::warning( "Error: getCustomButtonById71: Unexpected type of siteapp parent '$parentType'",'assert');
4597 }
4598 }
4599 else{
4600 if ( 'server' eq $parentType ) {
4601 $self->{packer}->addServerCustomButton( $id, $options, $customButtonsDir, $icon );
4602 }
4603 elsif ( 'client' eq $parentType || 'reseller' eq $parentType ) {
4604 $self->{packer}->addClientCustomButton( $parent, $id, $options, $customButtonsDir, $icon );
4605 }
4606 elsif ( 'domain-admin' eq $parentType ) {
4607 $self->{packer}->addDomainCustomButton( $parent, $id, $options, $customButtonsDir, $icon );
4608 }
4609 elsif ( 'mailuser' eq $parentType ) {
4610 $self->{packer}->addMailCustomButton( $parent, $id, $options, $customButtonsDir, $icon );
4611 }
4612 elsif ( 'sapp' eq $parentType ) {
4613 $self->{packer}->addSappCustomButton( $parent, $id, $options, $customButtonsDir, $icon );
4614 }
4615 else {
4616 Logging::warning("Error: getCustomButtonById71: Unexpected type of parent '$parentType'",'assert');
4617 }
4618 }
4619}
4620
4621sub getCustomButtonsByOwner71 {
4622 my ( $self, $owner_type, $owner_id ) = @_;
4623 my @ids = @{DAL::getCustomButtonIdsByOwner71($owner_type, $owner_id)};
4624 return unless @ids;
4625 return map { $self->getCustomButtonById71( $_, $owner_id, $owner_type ) } @ids;
4626}
4627
4628sub getCustomButtonsByOwner {
4629 my $self = shift;
4630 return $self->getCustomButtonsByOwner71(@_)
4631}
4632
4633sub makeAdminInfoNode {
4634 my ( $self, $embeddedInfo ) = @_;
4635
4636 my ( $max_btn_len, $send_announce, $external_id );
4637
4638 my $ptrAdmin = DAL::getAdminMiscParams();
4639
4640 if( exists $ptrAdmin->{'max_button_length'} ){
4641 $max_btn_len = $ptrAdmin->{'max_button_length'};
4642 delete $ptrAdmin->{'max_button_length'}
4643 }
4644 if( exists $ptrAdmin->{'send_announce'} ){
4645 $send_announce = $ptrAdmin->{'send_announce'};
4646 delete $ptrAdmin->{'send_announce'};
4647 }
4648
4649 $external_id = DAL::getClientExternalId( PleskStructure::getAdminId() );
4650
4651 $self->{packer}->addRootAdmin(PleskStructure::getAdminId(), PleskStructure::getAdminGuid(), DAL::getFullHostName());
4652
4653 my $passwd = AgentConfig::get { 'password' };
4654 my $cron = undef;
4655 if (defined($embeddedInfo->{'scheduled-tasks'})) {
4656 $cron = $embeddedInfo->{'scheduled-tasks'}->[0];
4657 }
4658
4659 my $subscriptionDescriptions = DAL::getSubscriptionsAdminDescriptions();
4660 my $clientsDescriptions = DAL::getClientsDescriptions( PleskStructure::getAdminId() );
4661 my @allAdminDescriptions = (@{$subscriptionDescriptions}, @{$clientsDescriptions});
4662
4663 $self->{packer}->setServerAdminInfo( $ptrAdmin, $passwd, $max_btn_len, $send_announce, $external_id, $cron, \@allAdminDescriptions );
4664
4665 my $adminClientParams = DAL::getAdminClientParams();
4666 my $adminId = PleskStructure::getAdminId();
4667 $self->{packer}->makeClParamNode($adminId, 'admin', $adminClientParams);
4668
4669 $self->makeAdminLimitsAndPermissions();
4670}
4671
4672sub dumpPlanItems {
4673 my ( $self) = @_;
4674
4675 my @planItems = @{DAL::getPlanItems()};
4676 if ( @planItems ) {
4677 my $customButtonsDir = AgentConfig::get("PRODUCT_ROOT_D") . '/admin/htdocs/images/custom_buttons';
4678 foreach my $planItemPtr ( @planItems ) {
4679 my %planItemProps = %{DAL::getPlanItemProperties($planItemPtr->{'id'})};
4680 if ( keys %planItemProps ) {
4681 $self->{packer}->addPlanItemToServer($planItemPtr, \%planItemProps, $customButtonsDir);
4682 }
4683 }
4684 }
4685}
4686
4687sub addServerIps {
4688 my ($self, $certPtr, $ipPtr) = @_;
4689
4690 foreach my $ptrHash (@{DAL::getServerIps($certPtr)}) {
4691 if (defined $ipPtr) {
4692 foreach my $domainIp (@{$ipPtr}) {
4693 if ($domainIp eq $ptrHash->{'ip_address'}) {
4694 $ptrHash->{'type' } = PleskStructure::isExclusiveIp( $ptrHash->{'ip_address'} ) ? 'exclusive' : 'shared';
4695 $self->{packer}->addServerIp($ptrHash);
4696 }
4697 }
4698 } else {
4699 $ptrHash->{'type' } = PleskStructure::isExclusiveIp( $ptrHash->{'ip_address'} ) ? 'exclusive' : 'shared';
4700 $self->{packer}->addServerIp($ptrHash);
4701 }
4702 }
4703}
4704
4705sub makeServerNode {
4706 my ( $self, $embeddedInfo ) = @_;
4707
4708 $self->checkProgramTerminated();
4709
4710 $self->{packer}->setServerSettings();
4711
4712 if ( $self->{shallow_dump} ) {
4713 return;
4714 }
4715
4716 #Dump server skeleton
4717 if ( !$self->{configuration_dump} && !$self->{only_mail_dump} ) {
4718 my $skeletonPath = AgentConfig::get('HTTPD_VHOSTS_D') . "/.skel/0";
4719 $self->{packer}->addServerSkeleton( $skeletonPath, "skel" );
4720
4721 my $customTemplatesPath = AgentConfig::get('PRODUCT_ROOT_D')."/admin/conf/templates/custom";
4722 if (-d $customTemplatesPath) {
4723 $self->{packer}->addServerCustomApacheTemplates($customTemplatesPath);
4724 }
4725
4726 $self->{packer}->setSb5ServerContent();
4727 $self->{packer}->addServerCustomHealthConfig();
4728
4729 if (-d AgentConfig::get('HTTPD_VHOSTS_D')."/fs") {
4730 $self->{packer}->addFileSharingContent(AgentConfig::get('HTTPD_VHOSTS_D')."/fs");
4731 }
4732 }
4733
4734 #Dump system and default ip
4735 $self->addServerIps();
4736
4737 #Dump hostname
4738 my $fullHostName = DAL::getFullHostName();
4739 $self->{packer}->setServerHostname($fullHostName) if $fullHostName;
4740
4741 #Dump connection information to Billing
4742 my %adminClientParams = %{DAL::getAdminClientParams()};
4743 $self->{packer}->setPpbConnection(\%adminClientParams);
4744
4745 # Dump database servers
4746 my %def = %{DAL::getDefaultServerParams()};
4747
4748 foreach my $ptrHash (@{DAL::getDatabaseServers()}) {
4749 my $param = 'default_server_' . $ptrHash->{'type'};
4750 my $default = exists $def{$param} && $def{$param} == $ptrHash->{'id'};
4751
4752 my $passwd;
4753 if ( $ptrHash->{'type'} eq 'mysql'
4754 && $ptrHash->{'host'} eq 'localhost' ) {
4755 $passwd = AgentConfig::get('password');
4756 }
4757 $self->{packer}->addServerDb( $ptrHash, $passwd, $default );
4758 }
4759
4760 my %params = %{DAL::getMisc()};
4761 my %mailSettings = %{DAL::getMailServerSettings()};
4762
4763 if( !$self->{configuration_dump} ){
4764 # Dump key info
4765 if (!$self->{no_license}) {
4766 my $phpini = AgentConfig::get('PRODUCT_ROOT_D') . "/admin/conf/php.ini";
4767 my $swkeyrepo = '/etc/sw/keys';
4768 if( -e $phpini ){
4769 open PHPINI, $phpini;
4770 while (<PHPINI>) {
4771 chomp;
4772 next if /^#/;
4773 next if /^$/;
4774 if ( $_ =~ /swkey\.repository_dir\s*=\s*[\"\']?(.+)[\"\']\s*$/) {
4775 $swkeyrepo = $1;
4776 Logging::debug( "Found sw key repository: $swkeyrepo" );
4777 last;
4778 }
4779 }
4780 close PHPINI;
4781 }
4782 if( -d "$swkeyrepo/keys" ){
4783 my $keyDir = "$swkeyrepo/keys";
4784 Logging::debug( "Load keys from '$keyDir'" );
4785 opendir DIR, "$keyDir";
4786 my @files = readdir( DIR );
4787 closedir DIR;
4788 foreach my $key(@files){
4789 if( $key ne '.' and $key ne '..' and -f "$keyDir/$key" ){
4790 my $cmd = AgentConfig::getLicenseCommand();
4791 if ($cmd) {
4792 $cmd .= " --get-instance-id $keyDir/$key";
4793 my $exec = `$cmd`;
4794 chomp($exec);
4795 $self->{packer}->addServerKey( $key, $key, $keyDir, 'false', $exec);
4796 }
4797 }
4798 }
4799 }
4800 else{
4801 Logging::warning( "Keys directory '$swkeyrepo/keys' is not found. The keys are not included to backup." ,'assert');
4802 }
4803 }
4804 }
4805
4806 # Dump server settings
4807
4808 $mailSettings{'rbl_server'} =~ s/;/,/g if ($mailSettings{'rbl_server'});
4809
4810 # Dump mail settings
4811 my $mailmng = AgentConfig::getMailmngServerUtil();
4812 my $letter_size = undef;
4813 if ( -e $mailmng ) {
4814 $letter_size = `$mailmng --get-max-letter-size`;
4815 chomp($letter_size);
4816 }
4817
4818 my @blackList = @{DAL::getBadmailfrom()};
4819 my %whiteList = %{DAL::getSmtpPoplocks()};
4820 my %ipAddresses = %{DAL::getIpAddresses()};
4821 my @externalWebmails = @{DAL::getExternalWebmail()};
4822 my $mailCertificate;
4823 if (exists $mailSettings{'inbound_ssl'} and $mailSettings{'inbound_ssl'} eq 'true' and exists $mailSettings{'inbound_ssl_cert_id'}) {
4824 my $certPk = $self->getDomainCertificatePrivateKey($mailSettings{'inbound_ssl_cert_id'});
4825 $mailCertificate = $self->getCertificateRef($certPk) if defined $certPk;
4826 }
4827 $self->{packer}->setServerMail($letter_size, \%params, \%mailSettings, \@blackList, \%whiteList, \%ipAddresses, \@externalWebmails, $mailCertificate);
4828 $self->{packer}->setServerDNS( \%params, DAL::getDnsRecsT() );
4829 $self->{packer}->setServerWebSettings($embeddedInfo);
4830
4831 my $defaultCert;
4832 foreach my $id (@{DAL::getCertificateIds($params{'cert_rep_id'})}) {
4833 if ( $params{'default_certificate_id'} == $id ) {
4834 $defaultCert = 1;
4835 }
4836 else {
4837 $defaultCert = 0;
4838 }
4839 $self->makeCertificateNode( $id, 0, 'server', $defaultCert );
4840 }
4841
4842 $self->{packer}->addPanelCertificate();
4843 $self->getCustomButtonsByOwner( 'server', 0 );
4844 $self->{packer}->setControlsVisibility( \%params );
4845 $self->{packer}->dumpUiMode(\%params);
4846
4847 my $adminId = PleskStructure::getAdminId();
4848 $self->dumpTemplates( $adminId, 'server', 'domain' );
4849 $self->dumpTemplates( $adminId, 'server', 'domain_addon' );
4850 $self->dumpTemplates( $adminId, 'server', 'reseller' );
4851 $self->dumpPlanItems();
4852
4853 if (!$self->{only_mail_dump}) {
4854 my %applicationsList = %{$self->getListOfInstalledApplicationsOnServer()};
4855
4856 foreach my $application ( keys %applicationsList ) {
4857 my @applicationInfo = @{$applicationsList{$application}};
4858 $self->{packer}->addServerAppPackage( $applicationInfo[0], $applicationInfo[1], $applicationInfo[2], $applicationInfo[3], $applicationInfo[4], $applicationInfo[5], $applicationInfo[6], $applicationInfo[7]);
4859 }
4860 }
4861
4862 $self->{packer}->setServerBackupSettings( \%params );
4863
4864 $self->dumpServerPreferences( \%params );
4865
4866 $self->makeSpamassassinNode(undef, "*", "*", undef, undef);
4867
4868 # Server wide grey-listing preferences
4869 my $glParams = DAL::getGLParams();
4870 $glParams->{'personal-conf'} = defined($mailSettings{'spamfilter_use_mailuser_prefs'}) ? $mailSettings{'spamfilter_use_mailuser_prefs'} : "false";
4871
4872 $self->{packer}->setGLServerSettings($glParams);
4873 $self->{packer}->addServerVirusfilter($mailSettings{'virusfilter'});
4874 $self->{packer}->setServerEventHandler($embeddedInfo);
4875 $self->{packer}->addServerSiteIsolationConfig();
4876 $self->dumpServerNotifications();
4877 $self->{packer}->addServerMailmanConfiguration();
4878
4879 if (exists $params{'theme_skin'} and not $self->{configuration_dump}) {
4880 $self->{packer}->makeSkinNode($params{'theme_skin'}, 'admin', undef);
4881 }
4882
4883 my %fsSettings = %{DAL::getFileSharingSettings()};
4884 $self->{packer}->dumpFileSharingServerSettings(\%fsSettings);
4885 if (!$self->{configuration_dump} && !$self->{only_mail_dump}) {
4886 $self->{packer}->dumpFileSharingUnlistedFiles(DAL::getFileSharingUnlistedFiles());
4887 }
4888
4889 $self->{packer}->setMiscParameters(\%params);
4890 $self->{packer}->addCustomizationConfig();
4891 $self->{packer}->addRestrictedDomains();
4892 $self->{packer}->addFail2ban();
4893 $self->addModSecurityContent($embeddedInfo);
4894 $self->{packer}->makeExtensionNode('server', '');
4895}
4896
4897sub dumpServerNotifications {
4898 my ( $self ) = @_;
4899
4900 my $expirationWarnDays = DAL::getExpirationWarnDays() || 1;
4901
4902 $self->{packer}->addServerNotifications( $expirationWarnDays, DAL::getNotifications(), DAL::getNotes() );
4903}
4904
4905sub dumpServerPreferences {
4906 my ( $self, $params ) = @_;
4907
4908 $self->{packer}->addServerPreferences( $params );
4909
4910 foreach my $access ( @{DAL::getCpAccess()} ) {
4911 $self->{packer}->addRestrictionItem( $access->[0], $access->[1], $access->[2] );
4912 }
4913
4914 if (defined($params->{'disable_mail_ui'})) {
4915 $self->{packer}->addDisableMailUiOption($params->{'disable_mail_ui'});
4916 }
4917 if (defined($params->{'crontab_secure_shell'}) || defined($params->{'crontab_secure_shell_compatibility_mode'})) {
4918 $self->{packer}->addCrontabSecureSettings($params);
4919 }
4920
4921 my $technicalDomainName = undef;
4922 if (defined($params->{'preview_zone_domain_id'})) {
4923 $technicalDomainName = DAL::getDomainNameById($params->{'preview_zone_domain_id'});
4924 } elsif (defined($params->{'preview_zone_external_domain_name'})) {
4925 $technicalDomainName = $params->{'preview_zone_external_domain_name'};
4926 }
4927 $self->{packer}->addTechnicalPreviewDomainNode($technicalDomainName) if $technicalDomainName;
4928
4929 my $autoUpdates = DAL::getSingleSmbSetting('automaticUpdates');
4930 my $autoUpdatesValue = (defined($autoUpdates) && $autoUpdates eq 'true') ? 'true' : 'false';
4931 my $autoUpgradeToStable = (defined($params->{'autoupgrade_to_stable'}) && $params->{'autoupgrade_to_stable'} eq 'true') ? 'true' : 'false';
4932 my $autoUpgradeBranch = (defined($params->{'autoupgrade_branch'})) ? $params->{'autoupgrade_branch'} : 'release';
4933
4934 $self->{packer}->addUpdateSettings($autoUpdatesValue, $autoUpgradeToStable, $autoUpgradeBranch);
4935
4936 my $ftpSettings = DAL::getFtpServerSettings();
4937 $self->{packer}->addFtpOverSslSettings($ftpSettings->{'ftpOverSsl'}) if exists $ftpSettings->{'ftpOverSsl'};
4938}
4939
4940sub getApsArchiveFileName {
4941 my ( $self, $distrib_path, $package_info ) = @_;
4942
4943 my %mapHash = MiscConfigParser::parseApsIndexFile( $distrib_path . "/archive-index.xml" );
4944 my $file_name;
4945
4946 foreach my $tfile_name ( keys %mapHash ) {
4947 if ( $package_info eq join( "-", @{ $mapHash{$tfile_name} } ) ) {
4948 $file_name = $tfile_name;
4949 }
4950 }
4951
4952 return $file_name;
4953}
4954
4955sub getDomainKeysDomainSupport {
4956 my ( $self, $domainId, $domainName, $dnsZoneId ) = @_;
4957
4958 my $state = DAL::getDomainKeysState($domainId);
4959 return unless defined $state;
4960
4961 my $publickKey = DAL::getDomainKeysPublicKey($domainName, $dnsZoneId);
4962
4963 $self->{packer}->setDomainKeysDomainSupport( $domainId, $domainName, $state,
4964 '/etc/domainkeys/' . $domainName, $publickKey );
4965}
4966
4967sub getOldWebMailStatus {
4968 my ($self, $dnsZoneId) = @_;
4969 my $sql;
4970 my $retCode = undef;
4971 $sql = "SELECT * FROM dns_recs WHERE dns_zone_id=?";
4972 if ( $self->{dbh}->execute_rownum($sql, $dnsZoneId) ) {
4973 while ( my $ptrHash = $self->{dbh}->fetchhash() ) {
4974 if ($ptrHash->{'displayHost'} =~ /.*webmail.*/) {
4975 $retCode = 1;
4976 }
4977 }
4978 }
4979 $self->{dbh}->finish();
4980 return $retCode;
4981}
4982
4983sub dumpApsBundle {
4984 my ($self, $parentId, $parentType) = @_;
4985
4986 my $properties = $self->getSubscriptionPropertiesHash($parentId, $parentType);
4987
4988 my $filterId = $properties->{'aps_bundle_filter_id'};
4989
4990 if (!$filterId or $filterId eq '') {
4991 return;
4992 }
4993
4994 my $filterType = DAL::getApsBundleFilterType($filterId);
4995 my $items = DAL::getApsBundleFilterItems($filterId);
4996 $self->{packer}->makeApsBundleFilterNode($parentId, $parentType, $filterType, $items, undef);
4997}
4998
4999sub getServiceIps {
5000 my ($self, $domainId, $service , $ip) = @_;
5001 my %serviceIpAdresses;
5002 my @ips = @{DAL::getServiceIps( $domainId, $service)};
5003 foreach my $serviceIpAddress (@ips) {
5004 $serviceIpAdresses{$serviceIpAddress} = PleskStructure::getIpType($serviceIpAddress);
5005 }
5006 return \%serviceIpAdresses;
5007}
5008
5009sub getConcreteApplicationInfo {
5010 my ( $self, $ptrApplications, $registryUid ) = @_;
5011 my @applications = @{$ptrApplications};
5012 foreach my $application ( @applications ) {
5013 if ( $application->getRegistryUid() eq $registryUid) {
5014 return $application;
5015 }
5016 }
5017}
5018
5019sub makeMailListsNode {
5020 my ($self, $domainId, $domainAsciiName, $ip) = @_;
5021
5022 if ( !$self->{only_hosting_dump} ) {
5023 Logging::debug("Dumping maillists");
5024 my $maillistsStatus = $self->getDomainMaillistStatus($domainId);
5025 if (defined $maillistsStatus) {
5026 my $serviceIps = $self->getServiceIps( $domainId, 'maillists', $ip);
5027 $self->{packer}->setDomainMailLists( $domainId, $maillistsStatus, $serviceIps);
5028
5029 my $archiveDir = AgentConfig::get("MAILMAN_VAR_D") . "/archives/private";
5030
5031 my @maillists = @{DAL::getDomainMaillists($domainId)};
5032 if ( @maillists ) {
5033 my @archiveDirs;
5034 for my $ptrRow ( @maillists ) {
5035 my $maillistDir = lc($ptrRow->[1]);
5036 push @archiveDirs, $maillistDir if -d "$archiveDir/" . $maillistDir;
5037 my $datafile = $maillistDir . ".mbox";
5038 push @archiveDirs, $datafile if -d "$archiveDir/$datafile";
5039 $self->makeMailmanMailListNode( $domainId, @{$ptrRow} );
5040 }
5041 if (@archiveDirs) {
5042 my $mailmanUserInfo = AgentConfig::getMailmanUserInfo();
5043 $self->{packer}->setDomainMailListContent( $domainId, $domainAsciiName, $archiveDir,
5044 { 'include' => \@archiveDirs, 'follow_symlinks' => 1, 'sysuser' => $mailmanUserInfo->{'user'}} );
5045 }
5046 }
5047 }
5048 } else {
5049 Logging::debug("Skip maillists due to settings");
5050 }
5051}
5052
5053sub generateObjectUuidForLogging {
5054 my $self = shift;
5055 return join('#', @_);
5056}
5057
5058sub getDomainParams {
5059 my ( $self, $domainPtr ) = @_;
5060 my %domain = %{$domainPtr};
5061 my %domainParams = %{DAL::getDomainParams($domain{'id'})};
5062 return \%domainParams;
5063}
5064
5065sub addUsers {
5066 my ( $self, $usersList, $callback, $callbackFailed ) = @_;
5067
5068 for my $userLogin ( @{$usersList} ) {
5069 eval {
5070 my $userHash = DAL::getUserHash( $userLogin );
5071 next if (! keys %$userHash); # if hash is empty (error occurred)
5072 my $assignedApplications = DAL::getUserAssignedApplications( $userHash->{'id'} );
5073 $userHash->{'assignedApplications'} = $assignedApplications;
5074 $callback->( $userLogin, $userHash );
5075 1;
5076 } or do {
5077 $self->excludeProblemUserFromBackup( $userLogin, $callbackFailed, $@ );
5078 }
5079 }
5080}
5081
5082sub addModSecurityContent {
5083 my ($self, $embeddedInfo) = @_;
5084 return unless defined($embeddedInfo->{'web-settings'});
5085
5086 my $ruleSet = '';
5087 foreach my $webSettings (@{$embeddedInfo->{'web-settings'}}) {
5088 if ('' eq $webSettings) {
5089 last;
5090 }
5091 foreach my $setting (@{$webSettings->{'setting'}}) {
5092 my ($name) = @{$setting->{'name'}};
5093 my ($value) = @{$setting->{'value'}};
5094 if ('ruleSet' eq $name) {
5095 $ruleSet = $value;
5096 last;
5097 }
5098 }
5099 }
5100 return if ('' eq $ruleSet);
5101
5102 my $rulesBaseDir = undef;
5103 my $cmd = AgentConfig::getModSecurityCtlUtil() . ' --rules-base-dir';
5104 Logging::debug("Exec: $cmd");
5105 my $ret = `$cmd`;
5106 if (0 == ($? >> 8)) {
5107 $rulesBaseDir = HelpFuncs::trim($ret);
5108 } else {
5109 Logging::warning('Cannot execute command: ' . $cmd . ', STDOUT: ' . $ret, 'UtilityError');
5110 return;
5111 }
5112
5113 my @ruleSetDirs = ();
5114 $cmd = AgentConfig::getModSecurityCtlUtil() . ' --list-rulesets';
5115 Logging::debug("Exec: $cmd");
5116 $ret = `$cmd`;
5117 if (0 == ($? >> 8)) {
5118 foreach my $ruleSetDir (split(/\n/, $ret)) {
5119 if ($ruleSetDir =~ /\.saved-\d+/) {
5120 next;
5121 }
5122 push(@ruleSetDirs, "$ruleSetDir/");
5123 }
5124 } else {
5125 Logging::warning('Cannot execute command: ' . $cmd . ', STDOUT: ' . $ret, 'UtilityError');
5126 return;
5127 }
5128
5129 if (@ruleSetDirs) {
5130 $self->{packer}->addModSecurityContent($rulesBaseDir, @ruleSetDirs);
5131 }
5132}
5133
5134sub getDomainCertificatePrivateKey {
5135 my ($self, $certificateId, $domainId) = @_;
5136
5137 if (0 != $certificateId) {
5138 return DAL::getCertificatePrivateKey($certificateId);
5139 }
5140 my @defaultCerts = @{$self->getDomainDefaultCert($domainId)};
5141 if (@defaultCerts) {
5142 return DAL::getCertificatePrivateKey($defaultCerts[0]);
5143 }
5144 return undef;
5145}
5146
5147sub getCertificateRef {
5148 my ($self, $privateKey) = @_;
5149
5150 my $md5 = PerlMD5->new();
5151 $md5->add(HelpFuncs::urlDecode($privateKey));
5152 return $md5->hexdigest();
5153}
5154
5155sub _initDomainContentStat {
5156 my ($self, $domainId) = @_;
5157
5158 my $sql = "SELECT httpdocs + httpsdocs, dbases, mailboxes FROM disk_usage WHERE dom_id=?";
5159 if ($self->{dbh}->execute_rownum($sql, $domainId)) {
5160 if (my $ptrRow = $self->{dbh}->fetchrow()) {
5161 $self->{packer}->{stat}{vhostSizeOnFS} += @{$ptrRow}[0];
5162 $self->{packer}->{stat}{dbSizeOnFS} += @{$ptrRow}[1];
5163 $self->{packer}->{stat}{mailSizeOnFS} += @{$ptrRow}[2];
5164 }
5165 }
5166 $self->{dbh}->finish();
5167}
5168
5169sub _reportDomainStatistics {
5170 my ($self) = @_;
5171
5172 my ($storageType, $storageName) = ('local', '');
5173 if (ref($self->{packer}->{storage}) =~ /Storage::ArchiveStorage/) {
5174 if ($self->{packer}->{storage}->{exportDir} =~ /^ftps?:\/\//) {
5175 $storageType = 'foreign-ftp';
5176 } elsif ($self->{packer}->{storage}->{exportDir} =~ /^ext:\/\/([^\/]+)/) {
5177 $storageType = 'extension';
5178 $storageName = $1;
5179 }
5180 }
5181
5182 my ($objectType, undef, undef, undef, $objectId) = @{$self->getMainDumpInfo()};
5183
5184 my $xml =
5185 "<stat>".
5186 "<storage>".
5187 "<type>".$storageType."</type>".
5188 "<name>".$storageName."</name>".
5189 "</storage>".
5190 "<object>".
5191 "<type>".$objectType."</type>".
5192 "<id>".$objectId."</id>".
5193 "</object>".
5194 "<dump>".
5195 "<incremental>".($self->getIncrementalCreationDate() ? 'true' : 'false')."</incremental>".
5196 "<size>".int($self->{packer}->{storage}->getDumpFilesSize()/1048576)."</size>".
5197 "</dump>".
5198 "<vhost>".
5199 "<count>".$self->{packer}->{stat}{vhostDumpsCount}."</count>".
5200 "<size>".$self->{packer}->{stat}{vhostSizeOnFS}."</size>".
5201 "<dumpsize>".$self->{packer}->{stat}{vhostSizeDumped}."</dumpsize>".
5202 "</vhost>".
5203 "<db>".
5204 "<count>".$self->{packer}->{stat}{dbDumpsCount}."</count>".
5205 "<size>".$self->{packer}->{stat}{dbSizeOnFS}."</size>".
5206 "<dumpsize>".$self->{packer}->{stat}{dbSizeDumped}."</dumpsize>".
5207 "</db>".
5208 "<mail>".
5209 "<count>".$self->{packer}->{stat}{mailDumpsCount}."</count>".
5210 "<size>".$self->{packer}->{stat}{mailSizeOnFS}."</size>".
5211 "<dumpsize>".$self->{packer}->{stat}{mailSizeDumped}."</dumpsize>".
5212 "</mail>".
5213 "</stat>";
5214
5215 my $cmd = AgentConfig::getBackupRestoreHelperUtil();
5216 push(@{$cmd}, '--report-backup-info', "\"$xml\"");
5217
5218 Logging::debug("Exec: @{$cmd}");
5219 `@{$cmd}`;
5220}
5221
5222sub _isDatabaseIncluded {
5223 my ($self, $id) = @_;
5224
5225 return 1 unless defined($self->{includeDatabases});
5226 return (grep { $_->{'id'} eq $id } @{$self->{includeDatabases}}) ? 1 : 0;
5227}
5228
5229sub _validateDatabaseIncluded {
5230 my ($self, $domainId, $domainName) = @_;
5231
5232 return unless defined($self->{extension_data}) and defined($self->{includeDatabases});
5233
5234 my @domainDatabases = @{DAL::getDomainDatabases($domainId)};
5235
5236 my @includeDatabases = ();
5237 foreach my $includedDatabase (@{$self->{includeDatabases}}) {
5238 if (grep { $_->{'id'} eq $includedDatabase->{'id'} } @domainDatabases) {
5239 push @includeDatabases, $includedDatabase;
5240 } else {
5241 Logging::warning(sprintf(
5242 "The database #%d passed by the extension '%s' does not exist or belong to the subscription '%s'. It shall not be backed up."
5243 , $includedDatabase->{'id'}, $self->{extension_data}->{name}, $domainName
5244 ));
5245 }
5246 }
5247 $self->{includeDatabases} = \@includeDatabases;
5248}
5249
5250sub _getIncludedDatabaseTables {
5251 my ($self, $id, $name, $existentTables) = @_;
5252
5253 return undef unless defined($self->{extension_data}) and defined($self->{includeDatabases});
5254
5255 my @database = grep { $_->{'id'} eq $id } @{$self->{includeDatabases}};
5256 return undef unless @database and defined($database[0]->{'table'}) and @{$database[0]->{'table'}};
5257
5258 my @includedTables = ();
5259 my @notExistentTables = ();
5260 foreach my $includedTable (@{$database[0]->{'table'}}) {
5261 if (grep { $_ eq $includedTable } @{$existentTables}) {
5262 push @includedTables, $includedTable;
5263 } else {
5264 push @notExistentTables, $includedTable;
5265 }
5266 }
5267 if (@notExistentTables) {
5268 Logging::warning(sprintf(
5269 "The following tables passed by the extension '%s' do not exist in the database #%d '%s': %s. %s"
5270 , $self->{extension_data}->{name}, $id, $name, join(', ', map {"'$_'"} @notExistentTables)
5271 , @includedTables ? 'They shall not be backed up.' : 'The database content shall not be backed up.'
5272 ));
5273 }
5274 return \@includedTables;
5275}
5276
5277sub isProgramTerminated {
5278 my ($self) = @_;
5279
5280 return 0 unless $self->{sessionPath};
5281 return (-e "$self->{sessionPath}/task_stopped") ? 1 : 0;
5282}
5283
5284sub checkProgramTerminated {
5285 my ($self) = @_;
5286
5287 if ($self->isProgramTerminated()) {
5288 die('Program has been terminated');
5289 }
5290}
5291
5292sub getMainDumpInfo {
5293 my ($self) = @_;
5294
5295 my ($type, $name, $normalizedName, $guid, $id);
5296 if ($self->{dump_all} && $self->{dump_all} == 1) {
5297 $type = 'server';
5298 } elsif (exists $self->{resellers} && scalar @{$self->{resellers}} > 0) {
5299 if (scalar @{$self->{resellers}} == 1) {
5300 $type = 'reseller';
5301 $name = $self->{resellers}->[0];
5302 $id = $self->getClientId($name);
5303 $normalizedName = $self->{packer}->{fnamecreator}->normalize_short_string($name, $id);
5304 $guid = $self->getClientGuid($name);
5305 } else {
5306 $type = 'server';
5307 }
5308 } elsif (exists $self->{clients} && scalar @{$self->{clients}} > 0) {
5309 if (scalar @{$self->{clients}} == 1) {
5310 $type = 'client';
5311 $name = $self->{clients}->[0];
5312 $id = $self->getClientId($name);
5313 $normalizedName = $self->{packer}->{fnamecreator}->normalize_short_string($name, $id);
5314 $guid = $self->getClientGuid($name);
5315 } else {
5316 $type = 'server';
5317 }
5318 } elsif (exists $self->{domains} && scalar @{$self->{domains}} > 0) {
5319 if (scalar @{$self->{domains}} == 1) {
5320 $type = 'domain';
5321 $name = $self->getDomainAsciiName($self->{domains}->[0]);
5322 $id = $self->getDomainId($self->{domains}->[0]);
5323 $normalizedName = $self->{packer}->{fnamecreator}->normalize_long_string($name, $id);
5324 $guid = $self->getDomainGuid($self->{domains}->[0]);
5325 } else {
5326 $type = 'server';
5327 }
5328 }
5329 return [$type, $name, $normalizedName, $guid, $id];
5330}
5331
53321;