<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;"># Copyright 1999-2017. Parallels IP Holdings GmbH. All Rights Reserved.
package Packer;

use strict;
use warnings;

use Status;
use HelpFuncs;
use Storage::FileNameCreator;
use ArchiveContent::ArchiveContent;
use CommonPacker;
use Mailman;
use Logging;
use PerlMD5;
use XPath;
use File::Temp;
use File::Basename qw(dirname);
use IPC::Run qw(run);
use Fcntl qw&lt; S_IROTH S_IWOTH S_ISDIR S_ISLNK &gt;;

use vars qw|@ISA|;

my $DEBUG = undef;

### Common function ###

sub new {
  my $self = {};
  bless( $self, shift );
  $self-&gt;_init(@_);
  return $self;
}

sub _init {
  my ( $self, $version, $storagePolicy ) = @_;

  XmlNode::resetCompatibilityProcs();

  $self-&gt;{storage} = $storagePolicy;
  $self-&gt;{version} = $version;
  $self-&gt;{base64} = HelpFuncs::makeMIMEBase64();
  $self-&gt;{fnamecreator} = Storage::FileNameCreator-&gt;new();
  $self-&gt;setBackupProfileFileName( 'backup' );
  $self-&gt;{ownerGuid} = '';
  $self-&gt;{ownerType} = '';
  $self-&gt;{roots} = [];
  $self-&gt;{content_transport_type} = 'archive';
  $self-&gt;{content_transport} = ArchiveContent::ArchiveContent-&gt;new( $self-&gt;{storage}, $self );
  $self-&gt;{decrypt_full_dump} = 0;
  $self-&gt;{apache_user} = AgentConfig::getApacheUserInfo();
  $self-&gt;{mailman_user} = AgentConfig::getMailmanUserInfo();
  $self-&gt;{incrementalCreationDate} = undef;
  $self-&gt;{lastIndexPath} = undef;
  $self-&gt;{lastIncrementFile} = undef;
  $self-&gt;{excludePatternsFile} = undef;
  $self-&gt;{relatedDumps} = ();
  
  $self-&gt;flushDumpStatistics();
}

sub flushDumpStatistics {
  my ($self) = @_;
  
  $self-&gt;{stat} = ();
  $self-&gt;{stat}{vhostDumpsCount} = 0;
  $self-&gt;{stat}{vhostSizeOnFS} = 0;
  $self-&gt;{stat}{vhostSizeDumped} = 0;
  
  $self-&gt;{stat}{dbDumpsCount} = 0;
  $self-&gt;{stat}{dbSizeOnFS} = 0;
  $self-&gt;{stat}{dbSizeDumped} = 0;
  
  $self-&gt;{stat}{mailDumpsCount} = 0;
  $self-&gt;{stat}{mailSizeOnFS} = 0;
  $self-&gt;{stat}{mailSizeDumped} = 0;
}

sub setContentTransport {
  my ($self) = @_;
  $self-&gt;{content_transport} = ArchiveContent::ArchiveContent-&gt;new($self-&gt;{storage}, $self);
}

sub getContentTransport {
  my ($self) = @_;
  return $self-&gt;{content_transport};
}

sub setBackupProfileFileName{
  my ($self, $profileName, $profileId ) = @_;
  $self-&gt;{backupname} = $self-&gt;{fnamecreator}-&gt;normalize_long_string( $profileName, $profileId );
  $profileId = '' if not defined $profileId;
  Logging::debug( "Set backup file name '$self-&gt;{backupname}' (profile '$profileName', id='$profileId')\n" );
  $self-&gt;{backupPrefix} = $profileName;
}

sub setIncrementalCreationDate{
  my ($self, $incrementalCreationDate) = @_;
  $self-&gt;{fnamecreator}-&gt;setIncrementalCreationDate($incrementalCreationDate);
  $self-&gt;{incrementalCreationDate} = $incrementalCreationDate;
}

sub getIncrementalCreationDate {
  my ($self) = @_;
  return $self-&gt;{incrementalCreationDate};
}

sub getCreationDate {
  my ($self) = @_;
  return $self-&gt;{fnamecreator}-&gt;getCreationDate();
}

sub setLastIndexPath{
  my ($self, $lastIndexPath) = @_;
  $self-&gt;{lastIndexPath} = $lastIndexPath;
}

sub setLastIncrementFile {
  my ($self, $lastIncrementFile) = @_;
  $self-&gt;{lastIncrementFile} = $lastIncrementFile;
}

sub setExcludePatternsFile {
  my ($self, $excludePatternsFile) = @_;
  $self-&gt;{excludePatternsFile} = $excludePatternsFile;
}

sub setBackupOwnerGuid{
  my ($self, $ownerGuid, $ownertype ) = @_;
  $ownerGuid = '' if not $ownerGuid;
  $self-&gt;{ownerGuid} = $ownerGuid;
  $ownertype = '' if not $ownertype;
  $self-&gt;{ownerType} = $ownertype;
  Logging::debug( "Set backup owner guid '$ownerGuid', type '$ownertype'\n" );
}

sub getBackupOwnerGuid{
  my ($self) = @_;
  return $self-&gt;{ownerGuid};
}

sub startCollectStorageStatistics {
  my $self = shift;

  $self-&gt;{storage}-&gt;startCollectStatistics();
}

sub getStorageStatistics {
  my $self = shift;

  return $self-&gt;{storage}-&gt;getStatistics();
}

sub setRoot {
  my ( $self, $description, $content, $dumpformat, $adminGuid, $embeddedInfo ) = @_;

  $self-&gt;{root} = XmlNode-&gt;new( 'migration-dump',
    'attributes' =&gt;
      { 'agent-name' =&gt; 'PleskX', 'dump-version' =&gt; $self-&gt;{version}, 'dump-original-version' =&gt; $self-&gt;{version} } );
  $self-&gt;{root}-&gt;setAttribute( 'content-included', $content ? 'true' : 'false' ) if defined $content;
  $self-&gt;{root}-&gt;setAttribute( 'dump-format', $dumpformat ) if defined $dumpformat;
  my $dumpinfo = $self-&gt;{root}-&gt;getChild( 'dump-info', 1 );
  if ($description) {
    $dumpinfo-&gt;addChild( XmlNode-&gt;new( 'description', 'content' =&gt; $description ) );
  }

  my $osDescriptionNode = XmlNode-&gt;new('os-description');
  $osDescriptionNode-&gt;setAttribute('type', 'unix');
  if (my $apacheUid = getpwnam($self-&gt;{apache_user}{'user'})) {
    $osDescriptionNode-&gt;setAttribute('apache-uid', $apacheUid);
  }
  if (my $apacheGid = getgrnam($self-&gt;{apache_user}{'group'})) {
    $osDescriptionNode-&gt;setAttribute('apache-gid', $apacheGid);
  }
  if (my $mailmanUid = getpwnam($self-&gt;{mailman_user}{'user'})) {
    $osDescriptionNode-&gt;setAttribute('mailman-uid', $mailmanUid);
  }
  if (my $mailmanGid = getgrnam($self-&gt;{mailman_user}{'group'})) {
    $osDescriptionNode-&gt;setAttribute('mailman-gid', $mailmanGid);
  }
  $dumpinfo-&gt;addChild($osDescriptionNode);

  my $cpDescriptionNode = XmlNode-&gt;new('cp-description');
  my $componentsInstalledNode = XmlNode-&gt;new('components-installed');
  my %packages = %{DAL::getSoftwarePackages()};
  while (my ($name, $version) = each(%packages)) {
    my $componentNode = XmlNode-&gt;new('component');
    $componentNode-&gt;setAttribute('name', $name);
    $componentsInstalledNode-&gt;addChild($componentNode);
  }
  $cpDescriptionNode-&gt;addChild($componentsInstalledNode);
  if (defined($embeddedInfo-&gt;{'services'})) {
    my ($services) = @{$embeddedInfo-&gt;{'services'}};
    $self-&gt;addEmbeddedInfo($cpDescriptionNode, 'services', $services);
  }
  $dumpinfo-&gt;addChild($cpDescriptionNode);

  my $contentTransportDescriptionNode = $self-&gt;{content_transport}-&gt;getContentTransportDescription();
  if ( defined $contentTransportDescriptionNode ) {
    my $contentTransportNode = XmlNode-&gt;new( 'content-transport' );
    $contentTransportNode-&gt;addChild( $contentTransportDescriptionNode );
    $dumpinfo-&gt;addChild ( $contentTransportNode );
  }

  if ($adminGuid) {
    $dumpinfo-&gt;addChild(XmlNode-&gt;new('server-id', 'content' =&gt; $adminGuid));
  }
}

sub _getRootForStorageFinish {
  my ($self, $dumpDirPath) = @_;
  
  my $dumpinfo = $self-&gt;{root}-&gt;getChild('dump-info', 0);
  $dumpinfo-&gt;removeChildren('related-dumps');

  if (exists $self-&gt;{relatedDumps}-&gt;{$dumpDirPath}) {
    my $relatedDumpsNode = XmlNode-&gt;new('related-dumps');
    $dumpinfo-&gt;addChild($relatedDumpsNode);
    foreach my $relatedDump ( @{$self-&gt;{relatedDumps}-&gt;{$dumpDirPath}} ) {
      $relatedDumpsNode-&gt;addChild(XmlNode-&gt;new('related-dump', 'content' =&gt; $relatedDump));
    }
  }
  return $self-&gt;{root};
}

sub setDecryptFullDump {
  my ($self) = @_;
  $self-&gt;{decrypt_full_dump} = 1;
  Logging::debug( "Set to decrypt full dump" );
}

sub turnOffContent{
  my ($self) = @_;
  $self-&gt;{skip_content} = 1;
  Logging::debug( "The dump of content is switched off" );
}

sub isRootNode{
  my ($self, $node) = @_;
  foreach my $root( @{$self-&gt;{roots}} ){
    return 1 if $root==$node;
  }
  return 0;
}

sub finishChild{
    my ($self, $node, $path, $fileName ) = @_;
    my $ret;
    if(scalar( @{$self-&gt;{roots}} )==1  &amp;&amp; $self-&gt;isRootNode($node) ) {
      $ret = $self-&gt;{storage}-&gt;finish( $self-&gt;_getRootForStorageFinish($path), $path, $fileName );
      die "Cannot create main dump file!" if $ret!=0;
      $ret = $self-&gt;{storage}-&gt;getMainDumpXmlRelativePath();
    }
    else {
      $ret = $self-&gt;{storage}-&gt;finishChild( $self-&gt;_getRootForStorageFinish($path), $node, $path, $fileName );
    }
    return $ret;
}

sub finishDomains {
  my ($self, $fileName, $fh, $usersContentSize, $infoxml) = @_;

  if ( exists $self-&gt;{domainNodes} ) {
    my ( $id, $node, $path );
    while ( ($id, $node ) = each( %{$self-&gt;{domainNodes}} ) ){
      $path = $self-&gt;getDomainsBackupPath( $id );
      Logging::debug( "Save domain dump $path" );
      XmlNode::setStartSavePath( $path );

      print $fh "&lt;file&gt;" . $path . "/" .$self-&gt;getDomainsBackupPath( $id, $fileName, 1 ) . ".xml" . "&lt;/file&gt;\n";

      my $fileid = $self-&gt;finishChild( $node, $path, $self-&gt;getDomainsBackupPath( $id, $fileName, 1 ) );
      my $contentSize = $self-&gt;getContentSize($node);
      @{$infoxml-&gt;{$fileid}} = ( $contentSize, $self-&gt;getDomainObjectId( $id ), $node-&gt;getAttribute('guid') );
      $self-&gt;{storage}-&gt;createRepositoryIndex( $node-&gt;getAttribute('guid') . '_' . $self-&gt;getDomainObjectId( $id ) );

      #Keep total domain content size for each client
      my $clientId = PleskStructure::getClientIdForDomainId( $id );
      $usersContentSize-&gt;{$clientId} = (exists $usersContentSize-&gt;{$clientId}) ? $usersContentSize-&gt;{$clientId} + $contentSize : $contentSize;
    }
  }
}

sub finishClients {
  my ($self, $fileName, $fh, $selectResellers, $usersContentSize, $infoxml) = @_;

  if( exists $self-&gt;{clientNodes} ){
    my ( $id, $node, $path );
    while( ($id, $node ) = each( %{$self-&gt;{clientNodes}} ) ){
      my $fname;
      if (exists $self-&gt;{resellersNodes}-&gt;{$id}) {
        next if !$selectResellers;

        $path = $self-&gt;getResellersBackupPath( $id );
        $fname = $self-&gt;getResellersBackupPath( $id, $fileName, 1 );
        Logging::debug( "Save reseller dump $path" );
      } else {
        next if $selectResellers;

        $path = $self-&gt;getClientsBackupPath( $id );
        $fname = $self-&gt;getClientsBackupPath( $id, $fileName, 1 );
        Logging::debug( "Save client dump $path" );
      }

      XmlNode::setStartSavePath( $path );

      print $fh "&lt;file&gt;" . $path . "/" . $fname. ".xml" . "&lt;/file&gt;\n";

      # Calculate current client size
      $usersContentSize-&gt;{$id} = (exists $usersContentSize-&gt;{$id})
        ? $usersContentSize-&gt;{$id} + $self-&gt;getContentSize($node)
        : $self-&gt;getContentSize($node);

      # Add current client size to the parent (reseller or admin) total content size
      my $parentId = PleskStructure::getClientParentId(PleskStructure::getClientNameFromId($id));
      $usersContentSize-&gt;{$parentId} = (exists $usersContentSize-&gt;{$parentId})
        ? $usersContentSize-&gt;{$parentId} + $usersContentSize-&gt;{$id}
        : $usersContentSize-&gt;{$id};

      my $fileid = $self-&gt;finishChild( $node, $path, $fname );
      @{$infoxml-&gt;{$fileid}} = ( $usersContentSize-&gt;{$id}, $self-&gt;getClientObjectId( $id ), $node-&gt;getAttribute('guid') );
      $self-&gt;{storage}-&gt;createRepositoryIndex( $node-&gt;getAttribute('guid') . '_' . $self-&gt;getClientObjectId( $id ) );
    }
  }
}

sub finishCustomers {
  my ($self, $fileName, $fh, $usersContentSize, $infoxml) = @_;
  $self-&gt;finishClients($fileName, $fh, 0, $usersContentSize, $infoxml);
}

sub finishResellers {
  my ($self, $fileName, $fh, $usersContentSize, $infoxml) = @_;
  $self-&gt;finishClients($fileName, $fh, 1, $usersContentSize, $infoxml);
}

sub finish {
    my ($self) = @_;

    my %infoxml;

    my $ret = 0;
    my $fileName;
    my $mainDumpXmlFile;

    if(scalar( @{$self-&gt;{roots}} )!=1 ){

        XmlNode::setStartSavePath( '' );

        $fileName = $self-&gt;{fnamecreator}-&gt;getFileName( '', $self-&gt;{backupname}, '', 'info' );

        $ret = $self-&gt;{storage}-&gt;finish( $self-&gt;_getRootForStorageFinish(''), '', $fileName );

        die "Cannot create main dump file!" if $ret!=0;

        $mainDumpXmlFile = $self-&gt;{storage}-&gt;getMainDumpXmlRelativePath();

        @{$infoxml{$mainDumpXmlFile}} = ( $self-&gt;getContentSize( $self-&gt;{root} ), $self-&gt;getAdminObjectId(), ( exists $self-&gt;{admin} ? $self-&gt;{admin}-&gt;getAttribute('guid') : $self-&gt;{ownerGuid} ) );
        $self-&gt;{storage}-&gt;createRepositoryIndex( ( exists $self-&gt;{admin} ? $self-&gt;{admin}-&gt;getAttribute('guid') : '' ) . '_' . $self-&gt;getAdminObjectId() );
    }
    $fileName = 'info';

    my ($fh, $targetFile);
    ($fh, $targetFile ) = File::Temp::tempfile( AgentConfig::getBackupTmpDir() . "/pmm-xmlFilesList-XXXXXX", UNLINK =&gt; 1 );

    print $fh "&lt;dump-files source-directory=\"".$self-&gt;{storage}-&gt;getFullOutputPath()."\"&gt;\n";
    print $fh "&lt;file&gt;" . $self-&gt;{storage}-&gt;getMainDumpXmlFile() . "&lt;/file&gt;\n" if $self-&gt;{storage}-&gt;getMainDumpXmlFile();

    my %usersContentSize; # Summary size of each customer, reseller and admin content

    $self-&gt;finishDomains($fileName, $fh, \%usersContentSize, \%infoxml);
    $self-&gt;finishCustomers($fileName, $fh, \%usersContentSize, \%infoxml);
    $self-&gt;finishResellers($fileName, $fh, \%usersContentSize, \%infoxml);

    if (exists $infoxml{$mainDumpXmlFile}) {
      my $adminId = PleskStructure::getAdminId();
      @{$infoxml{$mainDumpXmlFile}}[0] += $usersContentSize{$adminId} if exists $usersContentSize{$adminId};
    }

    print $fh "&lt;/dump-files&gt;";
    close $fh;


    if ($self-&gt;{decrypt_full_dump}) {
      $self-&gt;_decryptDump($targetFile);
    } else {
        $self-&gt;_encryptDump($targetFile);
    }

    my $path;

    #Create discovered files
    foreach my $fileid(  keys( %infoxml ) ){
       my $idx = rindex( $fileid, '/' );
       $path = $fileid;
       $path = substr( $path, 0, $idx ) if $idx&gt;0;
       my $xmlsize = 0;
       my $files;
       foreach my $id( keys( %infoxml ) ){
         if( $idx&lt;0 || index( $id, $path )==0 ){
            $files = $self-&gt;{storage}-&gt;getFilesFromId( $id );
            foreach my $filedata( @{$files} ) {
              $xmlsize += $filedata-&gt;[1];
            }
         }
       }
       $files = $self-&gt;{storage}-&gt;getFilesFromId( $fileid );
       if( scalar( @{$files} )==1 ){
          my $xmlfiledata = $files-&gt;[0];
          $xmlsize += @{$infoxml{$fileid}}[0];
          my $objId = @{$infoxml{$fileid}}[1];
          my $objGuid = @{$infoxml{$fileid}}[2];
          $self-&gt;{storage}-&gt;writeDiscovered( $self-&gt;{storage}-&gt;getFilePathFromId( $fileid ), $xmlfiledata-&gt;[0], $xmlsize, $self-&gt;{ownerGuid}, $self-&gt;{ownerType}, $objGuid, $objId );
       }
    }

    return 0;
}

sub _decryptDump {
  my ($self, $targetFile) = @_;

  eval {
    my $encryptCmd = AgentConfig::getEncryptUtil();
    push(@{$encryptCmd}, '--decrypt-by-plesk', '-backup-files-map', $targetFile);
    Logging::debug("Execute: @{$encryptCmd}");
    my $stderr;
    IPC::Run::run($encryptCmd, '2&gt;', \$stderr) or die($stderr);
  };
  if ($@) {
    Logging::error("Cannot decrypt dump file (this is not fatal error!): $@", 'UtilityError');
  }
}

sub _encryptDump {
  my ($self, $targetFile) = @_;
  my $cryptKey = $ENV{'PLESK_BACKUP_CRYPT_KEY'};
  delete $ENV{'PLESK_BACKUP_CRYPT_KEY'} if ($cryptKey);
  my $password = $ENV{'PLESK_BACKUP_PASSWORD'};
  delete $ENV{'PLESK_BACKUP_PASSWORD'} if ($password);

  eval {
    my $encryptCmd = AgentConfig::getEncryptUtil();
    push(@{$encryptCmd}, '--encrypt-by-plesk', '-backup-files-map', $targetFile);
    Logging::debug("Execute: @{$encryptCmd}");
    my $stderr;
    IPC::Run::run($encryptCmd, '2&gt;', \$stderr) or die($stderr);
  };
  if ($@) {
    Logging::error("Cannot encrypt dump file (this is not fatal error!): $@", 'UtilityError');
  }
    
  $ENV{'PLESK_BACKUP_CRYPT_KEY'} = $cryptKey if ($cryptKey);
  $ENV{'PLESK_BACKUP_PASSWORD'} = $password if ($password);
}

sub getContentSize{
  my ($self, $node) = @_;
  my $size = 0;

  foreach my $child ( $node-&gt;getChildren() ) {
    if( $child ) {
      my $childName = $child-&gt;getName();
      if( $childName &amp;&amp; $childName eq 'cid' ){
        if( !defined($child-&gt;getAttribute('referrer')) ) {
          foreach my $cid ( $child-&gt;getChildren() ){
            if ($cid-&gt;isAttributeExist('size')) {
              $size += $cid-&gt;getAttribute('size');
            }
          }
        }
      }
      else {
        $size += $self-&gt;getContentSize($child);
      }
    }
  }
  return $size;
}

### Server functions ###

sub setServerSettings {
  my ( $self ) = @_;
  my $serverNode = XmlNode-&gt;new('server');
  $self-&gt;{serverNode} = $serverNode;
}

sub addServerNodeToDump {
  my ( $self ) = @_;

  my $root = $self-&gt;{root};
  unless (defined $root)
  {
    Logging::warning("Root node is not set", 'PackerStructure');
    return;
  }

  if ( ref ($self-&gt;{serverNode}) =~ /XmlNode/ ) {
    $root-&gt;addChild($self-&gt;{serverNode});
  }
}

sub addPanelCertificate {
  my ($self) = @_;
  my $serverNode = $self-&gt;{serverNode};

  my $path = AgentConfig::get('PRODUCT_ROOT_D') . "/admin/conf";
  my $httpsdFilename = 'httpsd.pem';

  if ( -e "$path/$httpsdFilename") {
    my $certNode = XmlNode-&gt;new('panel-certificate');

    my $content = undef;

    open HTTPSDFILE, $path . "/" . $httpsdFilename;
    binmode(HTTPSDFILE);
    while (&lt;HTTPSDFILE&gt;) {
      $content .= $_;
    }
    close HTTPSDFILE;

    $certNode-&gt;addChild(XmlNode-&gt;new('cp-certificate', 'content' =&gt; $self-&gt;{base64}-&gt;{'ENCODE'}-&gt;($content) ));

    my $rootchainFilename = 'rootchain.pem';
    if ( -e "$path/$rootchainFilename") {
      my $content = undef;
      open ROOTCHAINFILE, $path . "/" . $rootchainFilename;
      binmode(ROOTCHAINFILE);
      while (&lt;ROOTCHAINFILE&gt;) {
        $content .= $_;
      }
      close ROOTCHAINFILE;
      $certNode-&gt;addChild(XmlNode-&gt;new('cp-rootchain', 'content' =&gt; $self-&gt;{base64}-&gt;{'ENCODE'}-&gt;($content) ));
    }

    $serverNode-&gt;getChild( 'certificates', 1 )-&gt;addChild($certNode);
  }
}

sub addServerSiteIsolationConfig {
  my ($self) = @_;
  my $root = $self-&gt;{serverNode};

  my $path = AgentConfig::get('PRODUCT_ROOT_D') . "/admin/conf";
  my $file = 'site_isolation_settings.ini';

  if ( -e "$path/$file") {

    my $siteIsolationNode = XmlNode-&gt;new('site-isolation');

    my $configText = undef;

    open CONFIGFILE, $path . "/" . $file;
    binmode(CONFIGFILE);

    while (&lt;CONFIGFILE&gt;) {
      $configText .= $_;
    }

    close CONFIGFILE;

    $siteIsolationNode-&gt;addChild(XmlNode-&gt;new('config', 'content' =&gt; $self-&gt;{base64}-&gt;{'ENCODE'}-&gt;($configText) ));
    $root-&gt;addChild($siteIsolationNode);
  }
}

sub setServerEventHandler {
  my ($self, $ptrEvents, $ptrActions, $ptrParams) = @_;

  my $root = $self-&gt;{serverNode};
  my %events = %{$ptrEvents};
  my @actions = @{$ptrActions};
  my %params = %{$ptrParams};

  my $eventsNode = XmlNode-&gt;new('events');

  my $rotationNode = XmlNode-&gt;new('rotation');
  if ($params{'actionlog_rot_type'} eq 'forever') {
    $rotationNode-&gt;addChild(XmlNode-&gt;new('disabled'));
  }elsif($params{'actionlog_rot_type'} eq 'by_period') {
    my $byTimeNode = XmlNode-&gt;new('by-time');
    $byTimeNode-&gt;setAttribute('period-type', $params{'actionlog_rot_period'});
    $byTimeNode-&gt;setAttribute('period', $params{'actionlog_rot_num_periods'} );
    $rotationNode-&gt;addChild($byTimeNode);
  }elsif($params{'actionlog_rot_type'} eq 'by_number') {
    my $byNumberNode = XmlNode-&gt;new('by-entires');
    $byNumberNode-&gt;setAttribute('count', $params{'actionlog_rot_num_records'});
    $rotationNode-&gt;addChild($byNumberNode);
  }

  $eventsNode-&gt;addChild($rotationNode);

  foreach my $action (@actions) {
    my $eventNode = XmlNode-&gt;new('event');
    $eventNode-&gt;setAttribute('enabled', $action-&gt;{'enabled'});
    $eventNode-&gt;setAttribute('description', $action-&gt;{'descr'});
    $eventNode-&gt;setAttribute('name', $action-&gt;{'name'});
    if (exists $events{$action-&gt;{'id'}}) {
      foreach my $handler (@{$events{$action-&gt;{'id'}}}) {
        my $handlerNode = XmlNode-&gt;new('handler');
        $handlerNode-&gt;setAttribute('command', $handler-&gt;{'command'});
        $handlerNode-&gt;setAttribute('user', $handler-&gt;{'user'});
        $handlerNode-&gt;setAttribute('priority', $handler-&gt;{'priority'});
        $eventNode-&gt;addChild($handlerNode);
      }
    }
    $eventsNode-&gt;addChild($eventNode);
  }

  $root-&gt;addChild($eventsNode);
}

sub addServerNotifications {
  my ( $self, $expirationWarnDays, $ptrNotifications, $ptrNotes ) = @_;
  my $root = $self-&gt;{serverNode};
  my @notifications = @{$ptrNotifications};
  my %notes = %{$ptrNotes};

  my $notificationsNode = XmlNode-&gt;new('notifications');
  $notificationsNode-&gt;setAttribute( 'expiration-warning-days', $expirationWarnDays);
  foreach my $notification (@notifications) {
    my $notificationNode = XmlNode-&gt;new( 'notification' );
    $notificationNode-&gt;setAttribute( 'id',            $notification-&gt;{'id'} );
    $notificationNode-&gt;setAttribute( 'send2admin',    $notification-&gt;{'send2admin'}    ? 'true' : 'false' );
    $notificationNode-&gt;setAttribute( 'send2reseller', $notification-&gt;{'send2reseller'} ? 'true' : 'false' );
    $notificationNode-&gt;setAttribute( 'send2client',   $notification-&gt;{'send2client'}   ? 'true' : 'false' );
    $notificationNode-&gt;setAttribute( 'send2email',    $notification-&gt;{'send2email'}    ? 'true' : 'false' );

    $notificationNode-&gt;setAttribute( 'email', $notification-&gt;{'email'} ) if defined $notification-&gt;{'email'};
    $notificationNode-&gt;setAttribute( 'subj',  $notification-&gt;{'subj'} ) if defined $notification-&gt;{'subj'};

    my $noteText = (exists $notes{$notification-&gt;{'note_id'}}) ? $notes{$notification-&gt;{'note_id'}} : '';
    $notificationNode-&gt;addChild( XmlNode-&gt;new( 'notice-text', 'content' =&gt; $noteText ) );
    
    $notificationsNode-&gt;addChild( $notificationNode );
  }

  $root-&gt;addChild($notificationsNode);
}

sub addServerCustomButton {
  my ( $self, $id, $optionsPtr, $customButtonsDir, $icon ) = @_;

  my $parent = $self-&gt;{serverNode};
  if ( !defined($parent) ) {
    Logging::warning('Unable to dump custom buttons settings, because of dump XML structure is not full', 'PackerStructure');
    return;
  }

  my $node = $self-&gt;makeCustomButtonNode( 'admin', undef, $id, $optionsPtr, $customButtonsDir, $icon );

  $parent-&gt;getChild( 'interface-preferences', 1 )-&gt;addChild($node);
}

my %dumpedSystemIps;

sub addServerIp {
  my ( $self, $ip ) = @_;

  $self-&gt;setServerSettings() unless defined $self-&gt;{serverNode};

  if ( ! $dumpedSystemIps{$ip-&gt;{'ip_address'}} ) {
    $self-&gt;makeSystemIpNode( $self-&gt;{serverNode}, $ip );
    $dumpedSystemIps{$ip-&gt;{'ip_address'}} = 1;
  }
}

sub setServerDefaultIp {
  my ( $self, $ip ) = @_;

  my $parent = $self-&gt;{serverNode};
  if ( !defined($parent) ) {
    Logging::warning('Unable to dump server default IP, because of dump XML structure is not full', 'PackerStructure');
    return;
  }

  $parent-&gt;getChild( 'properties', 1 )-&gt;addChild( XmlNode-&gt;new( 'default-ip', 'content' =&gt; $ip ) );
}

sub setServerHostname {
  my ( $self, $hostname ) = @_;

  my $parent = $self-&gt;{serverNode};
  if ( !defined($parent) ) {
    Logging::warning('Unable to dump server host name, because of dump XML structure is not full', 'PackerStructure');
    return;
  }

  $parent-&gt;getChild( 'properties', 1 )-&gt;addChild( XmlNode-&gt;new( 'hostname', 'content' =&gt; $hostname ) );
}

sub setServerAdminInfo {
  my ( $self, $ptrAdmin, $passwd, $max_btn_len, $send_announce, $external_id, $cron, $descriptions ) = @_;

  my $parent = $self-&gt;{admin};
  if ( !defined($parent) ) {
    Logging::warning('Unable to dump server admin user information, because of dump XML structure is not full', 'PackerStructure');
    return;
  }

  $parent-&gt;setAttribute( 'max-button-length', $max_btn_len ) if $max_btn_len;
  $parent-&gt;setAttribute( 'send-announce', $send_announce ) if $send_announce;
  $parent-&gt;setAttribute( 'external-id', $external_id ) if defined $external_id and $external_id ne '';

  my %adminInfo = (
    'cname' =&gt; 'company',
    'phone'   =&gt; 'phone',
    'fax'     =&gt; 'fax',
    'address' =&gt; 'address',
    'city'    =&gt; 'city',
    'state'   =&gt; 'state',
    'pcode'   =&gt; 'zip',
    'country' =&gt; 'country',
    'email'   =&gt; 'email',
    'pname'   =&gt; 'name',
    'locale'  =&gt; 'locale',
  );

  my $pref = $parent-&gt;getChild( 'preferences', 1 );
  while ( my ( $name, $value ) = each( %{$ptrAdmin} ) ) {

    #Attributes transformation. Bug 97408
    $name =~ s/^admin_//g;
    next if not defined $adminInfo{$name};
    $pref-&gt;addChild( XmlNode-&gt;new( 'pinfo', 'attributes' =&gt; { 'name' =&gt; $adminInfo{$name} }, 'content'    =&gt; $value ) );
  }

  if (defined $cron) {
    $self-&gt;addEmbeddedInfo($pref, 'scheduled-tasks', $cron);
  }

  $self-&gt;makeDescriptionsNode( $pref, $descriptions );
}

sub addServerDb {
  my ( $self, $dbServerPtr, $passwd, $default ) = @_;

  my %dbServer = %{$dbServerPtr};

  my $parent = $self-&gt;{serverNode};
  if ( !defined($parent) ) {
    Logging::warning('Unable to dump server database, because of dump XML structure is not full', 'PackerStructure');
    return;
  }

  my $dbServerNode = $self-&gt;makeDbServerNodeWithoutCredentials(\%dbServer);

  if ( $default ) {
    $dbServerNode-&gt;setAttribute( 'default', 'true' );
  }

  if ( ($dbServer{'admin_login'}) and ($dbServer{'admin_login'} ne '')) {
    my $adminNode =
      XmlNode-&gt;new( 'db-admin',
      "attributes" =&gt; { "name" =&gt; "$dbServer{'admin_login'}" } );
    if ( $dbServer{'type'} eq 'mysql'
      &amp;&amp; $dbServer{'host'} eq 'localhost' )
    {
      $dbServer{'admin_password'} = $passwd;
    }
    my $passwordNode =
      CommonPacker::makePasswordNode( $dbServer{'admin_password'}, 'plain' )
      ;    # password type for dbservers is always plain
    $adminNode-&gt;addChild($passwordNode);

    $dbServerNode-&gt;addChild($adminNode);
  }

  $parent-&gt;getChild( 'db-servers', 1 )-&gt;addChild($dbServerNode);
}

sub makeDbServerNodeWithoutCredentials {
  my ($self, $dbServer) = @_;

  my $dbServerNode = XmlNode-&gt;new('db-server');

  $dbServerNode-&gt;setAttribute( 'type', $dbServer-&gt;{'type'} );

  $dbServerNode-&gt;addChild( XmlNode-&gt;new( 'host', 'content' =&gt; "$dbServer-&gt;{'host'}" ) );
  $dbServerNode-&gt;addChild( XmlNode-&gt;new( 'port', 'content' =&gt; "$dbServer-&gt;{'port'}" ) );

  return $dbServerNode;
}

sub makeDatabaseUserRemoteAccessRulesNode {
    my ($self, $dbUser, $dbId) = @_;

    Logging::debug("Backing up remote access rules for db user " . $dbUser-&gt;{'login'});
    my @rules = @{DAL::DatabaseUserRemoteAccessRules($dbUser-&gt;{'login'}, $dbId)};
    if ( @rules ) {
        my $rulesNode = XmlNode-&gt;new('remote-access-rules');
        for my $ptrRow ( @rules ) {
            my $ruleItemNode = XmlNode-&gt;new( 'rule-item' );
            $ruleItemNode-&gt;setAttribute( 'type', $ptrRow-&gt;[0] );
            $ruleItemNode-&gt;setAttribute( 'ip-address', $ptrRow-&gt;[1] );
            $ruleItemNode-&gt;setAttribute( 'ip-subnet-mask', $ptrRow-&gt;[2] );
            $rulesNode-&gt;addChild( $ruleItemNode );
        }

        return $rulesNode;
    }

    return;
}

sub addServerKey {
  my ( $self, $keyId, $keyName, $keyDir, $additional, $instance ) = @_;

  my $parent = $self-&gt;{serverNode};
  if ( !defined($parent) ) {
    Logging::warning('Unable to dump server license key, because of dump XML structure is not full', 'PackerStructure');
    return;
  }

  if ( -e "$keyDir/$keyName" ) {

    my $keyNode =
      XmlNode-&gt;new( 'key',
      'attributes' =&gt; { 'additional' =&gt; $additional } );

    $keyNode-&gt;setAttribute('instance-id', $instance) if $instance ne '';

    my $cid = $self-&gt;{content_transport}-&gt;addAdminContent(
      'key',
      undef,
      "$keyId.key",
      "directory" =&gt; $keyDir,
      "include"   =&gt; [$keyName]
    );
    $keyNode-&gt;getChild( 'content', 1, 1 )-&gt;addChild($cid) if $cid;

    $parent-&gt;getChild( 'keys', 1 )-&gt;addChild($keyNode);
  }

}

sub setServerMail {
  my ( $self, $letterSize, $paramsPtr, $mailSettingsPtr, $blackListPtr, $whiteListPtr, $ipAddressesPtr, $externalWebmailsPtr, $mailCertificate ) = @_;

  my %params = %{$paramsPtr};
  my %mailSettings = %{$mailSettingsPtr};
  my @blackList = @{$blackListPtr};
  my %whiteList = %{$whiteListPtr};
  my @externalWebmails = @{$externalWebmailsPtr};

  my $parent = $self-&gt;{serverNode};
  if ( !defined($parent) ) {
    Logging::warning('Unable to dump server mail settings, because of dump XML structure is not full', 'PackerStructure');
    return;
  }

  my $mailNode = XmlNode-&gt;new(
    'mail-settings',
    'attributes' =&gt; {
      'relay'           =&gt; $mailSettings{'relay'},
      'use-vocabulary'  =&gt; (defined($params{'use_vocabulary'}) and ($params{'use_vocabulary'} eq 'true'))
        ? 'true'
        : 'false',
      'short-pop3-names' =&gt; (defined($params{'allow_short_pop3_names'}) and ($params{'allow_short_pop3_names'})) eq 'enabled'
        ? 'true'
        : 'false',
      'message-submission' =&gt; (defined($mailSettings{'message_submission'}) and ($mailSettings{'message_submission'} eq 'true'))
        ? 'true'
        : 'false',
      'sign-outgoing-mail' =&gt; (defined($mailSettings{'domain_keys_sign'}) and ($mailSettings{'domain_keys_sign'} eq 'true'))
        ? 'true'
        : 'false',
      'verify-incoming-mail' =&gt; (defined($mailSettings{'domain_keys_verify'}) and ($mailSettings{'domain_keys_verify'} eq 'true'))
        ? 'true'
        : 'false',
    }
  );

  if (defined $letterSize) {
    $mailNode-&gt;setAttribute('max-letter-size', $letterSize);
  }
  if (defined $mailSettings{'courier_max_connections'}) {
    $mailNode-&gt;setAttribute('courier-max-connections', $mailSettings{'courier_max_connections'});
  }
  if (defined $mailSettings{'courier_max_connections_per_ip'}) {
    $mailNode-&gt;setAttribute('courier-max-connections-per-ip', $mailSettings{'courier_max_connections_per_ip'});
  }
  if (defined $mailSettings{'dovecot_max_connections'}) {
    $mailNode-&gt;setAttribute('dovecot-max-connections', $mailSettings{'dovecot_max_connections'});
  }
  if (defined $mailSettings{'dovecot_max_connections_per_ip'}) {
    $mailNode-&gt;setAttribute('dovecot-max-connections-per-ip', $mailSettings{'dovecot_max_connections_per_ip'});
  }
  if (defined $mailSettings{'dmarc_policy'}) {
    $mailNode-&gt;setAttribute('dmarc-enabled', $mailSettings{'dmarc_policy'} eq 'true' ? 'true' : 'false');
  }

  $mailNode-&gt;setAttribute('certificate', $mailCertificate) if defined $mailCertificate;

  my $spfNode = XmlNode-&gt;new(
    'spf',
    'attributes' =&gt; {
      'status' =&gt; (exists $mailSettings{'spf_enabled'} and $mailSettings{'spf_enabled'} eq 'true') ? 'true' : 'false'
    }
  );
  $spfNode-&gt;setAttribute('spf-behavior', (exists $mailSettings{'spf_behavior'} and "$mailSettings{'spf_behavior'}" ne '' ) ? $mailSettings{'spf_behavior'} : 1);
  if (exists $mailSettings{'spf_dnserrignore'}) {
    $spfNode-&gt;setAttribute('spf-ignore-dns-error', $mailSettings{'spf_dnserrignore'} eq 'true' ? 'true' : 'false');
  }

  $spfNode-&gt;addChild( XmlNode-&gt;new( 'spf-rules', 'content' =&gt; exists $mailSettings{'spf_rules'} ? $mailSettings{'spf_rules'} : '' ) );
  $spfNode-&gt;addChild( XmlNode-&gt;new( 'spf-guess', 'content' =&gt; exists $mailSettings{'spf_guess'} ? $mailSettings{'spf_guess'} : '' ) );
  $spfNode-&gt;addChild( XmlNode-&gt;new( 'spf-exp', 'content' =&gt; exists $mailSettings{'spf_exp'} ? $mailSettings{'spf_exp'} : '' ) );

  $mailNode-&gt;addChild($spfNode);

  my $rblNode = XmlNode-&gt;new(
    'rbl',
    'attributes' =&gt; {
        'status' =&gt; ( exists $mailSettings{'rbl'} and $mailSettings{'rbl'} eq 'true' )
      ? 'true'
      : 'false'
    }
  );
  $rblNode-&gt;addChild( XmlNode-&gt;new( 'rbl-server', 'content' =&gt; exists $mailSettings{'rbl_server'} ? $mailSettings{'rbl_server'} : '' ) );

  $mailNode-&gt;addChild($rblNode);

  if ( $mailSettings{'relay'} eq 'auth' ) {
    $mailNode-&gt;setAttribute( 'pop-auth', my $disable_pop_auth = (exists $mailSettings{'disable_pop_auth'} and $mailSettings{'disable_pop_auth'} ? 'false' : 'true') );
    $mailNode-&gt;setAttribute( 'smtp-auth', (exists $mailSettings{'disable_smtp_auth'} and $mailSettings{'disable_smtp_auth'} ? 'false' : 'true') );
    $mailNode-&gt;setAttribute( 'poplock-time', $mailSettings{'poplock_time'} )  if ('false' eq $disable_pop_auth);
  }

  # black list
  my $listNode = XmlNode-&gt;new('black-list');

  for my $listItem (@blackList) {
    $listNode-&gt;addChild( XmlNode-&gt;new( 'list-item', 'content' =&gt; $listItem ) );
  }
  $mailNode-&gt;addChild($listNode);

  # white list
  $listNode = XmlNode-&gt;new('white-list');

  for my $key (keys %whiteList) {
    $listNode-&gt;addChild(
      XmlNode-&gt;new(
        'list-item', 'content' =&gt; $key . '/' . $whiteList{$key}
      )
    );
  }
  $mailNode-&gt;addChild($listNode);

  $parent-&gt;addChild($mailNode);
  
  if (@externalWebmails) {
    $self-&gt;_makeExternalWebmails(\@externalWebmails);
  }

  for my $key (keys %mailSettings) {
    if ($key =~ /^outgoing_messages_/) {
      $self-&gt;_makeServerOutgoingMessagesParameter($key, $mailSettings{$key});
    }
  }

  $self-&gt;_makeSeverOutgoingEmailMode($mailSettingsPtr, $ipAddressesPtr);
}

sub setServerDNS {
  my ( $self, $paramsPtr, $recordsPtr ) = @_;

  my @records = @{$recordsPtr};

  my %params = %{$paramsPtr};

  my $parent = $self-&gt;{serverNode};
  if ( !defined($parent) ) {
    Logging::warning('Unable to dump server DNS settings, because of dump XML structure is not full', 'PackerStructure');
    return;
  }

  # dump dns
  my $dnsSettingsAttributes = {};
  if (defined $params{'dns_recursion'} and ($params{'dns_recursion'} eq 'any' or $params{'dns_recursion'} eq 'localnets' or $params{'dns_recursion'} eq 'localhost')) {
    $dnsSettingsAttributes = {
      'recursion' =&gt; $params{'dns_recursion'}
    }
  }
  my $dnsNode = XmlNode-&gt;new(
    'dns-settings',
    'attributes' =&gt; $dnsSettingsAttributes
  );

  my $dnsZone = XmlNode-&gt;new(
    'dns-zone',
    'attributes' =&gt;
      { 'email' =&gt; 'root@localhost.localdomain', 'type' =&gt; 'master' },
    'children' =&gt;
      [ Status::make( (not exists $params{'dns_zone_status'} or $params{'dns_zone_status'} ne 'false') ? 0 : 16 ) ]
  );

  $dnsZone-&gt;setAttribute( 'serial-format', $params{'soa_serial_format'} ) if exists $params{'soa_serial_format'};

  my %zone_params = (
    'ttl'     =&gt; 1 * 86400,
    'refresh' =&gt; 3 * 3600,
    'retry'   =&gt; 1 * 3600,
    'expire'  =&gt; 7 * 86400,
    'minimum' =&gt; 3 * 3600
  );

  my %zone_units = (
    'ttl'     =&gt; 86400,
    'refresh' =&gt; 3600,
    'retry'   =&gt; 3600,
    'expire'  =&gt; 86400,
    'minimum' =&gt; 3600
  );

  foreach my $zone_param ( keys %zone_params ) {
    my $soa_param = 'soa_' . $zone_param;

    $dnsZone-&gt;addChild(
      $self-&gt;makeDnsZoneParam(
        $zone_param,
        exists $params{ $soa_param . '_unit' }
        ? $params{ $soa_param . '_unit' }
        : $zone_units{$zone_param},
        exists $params{$soa_param} ? $params{$soa_param}
        : $zone_params{$zone_param},
      )
    );
  }

  # dns records
  for my $ptrHash (@records) {
    my $dnsrec = $self-&gt;makeDnsRecord($ptrHash);
    if ($dnsrec) {
      $dnsZone-&gt;addChild($dnsrec);
    }
  }

  $dnsNode-&gt;addChild($dnsZone);

  # dump common acl for dns zone

  my $aclNode = XmlNode-&gt;new('common-acl');

  foreach my $param ( keys %params ) {
    if ( $param =~ /^DNS_Allow_Transfer/ ) {
      $aclNode-&gt;addChild( XmlNode-&gt;new( 'list-item', 'content' =&gt; $params{$param} ) );
    }
  }

  $dnsNode-&gt;addChild($aclNode);

  my $subdomainOwnZone = 'false';
  if (exists($params{'subdomain_own_zones'})) {
    $subdomainOwnZone =  $params{'subdomain_own_zones'} eq 'false' ? 'false' : 'true';
  }else {
    $subdomainOwnZone = 'false';
  }

  $dnsNode-&gt;addChild( XmlNode-&gt;new( 'subdomain-own-zones', 'content' =&gt; $subdomainOwnZone ) );

  $parent-&gt;addChild($dnsNode);
}

sub setServerWebSettings {
  my ($self, $embeddedInfo) = @_;

  if (defined($embeddedInfo-&gt;{'web-settings'})) {
    my ($webSettings) = @{$embeddedInfo-&gt;{'web-settings'}};
    $self-&gt;addEmbeddedInfo($self-&gt;{serverNode}, 'web-settings', $webSettings);
  }
}

sub addEmbeddedInfo {
  my ($self, $parentNode, $embeddedNodeName, $embeddedInfo) = @_;

  eval {require XML::Simple; 1;};
  my $xs = XML::Simple-&gt;new(ForceArray =&gt; 1);
  my $embeddedInfoXml = $xs-&gt;XMLout($embeddedInfo, RootName =&gt; $embeddedNodeName);
  $embeddedInfoXml = Encode::encode('UTF-8', $embeddedInfoXml); # workaround for UTF8 symbols
  $parentNode-&gt;addChild(XmlNode-&gt;new(undef, 'raw' =&gt; $embeddedInfoXml));
}

sub addServerCertificate {
  my ( $self, $name, $cert, $csr, $ca_cert, $pvt_key, $default) = @_;

  my $parent = $self-&gt;{serverNode};
  if ( !defined($parent) ) {
    Logging::warning('Unable to dump server certificate, because of dump XML structure is not full', 'PackerStructure');
    return;
  }

  my $root = XmlNode-&gt;new('certificate');

  addUrlDecodedTextNode( $root, 'certificate-data', $cert ) if defined($cert);
  addUrlDecodedTextNode( $root, 'signing-request',  $csr ) if defined($csr);
  addUrlDecodedTextNode( $root, 'ca-certificate',   $ca_cert ) if defined($ca_cert);
  addUrlDecodedTextNode( $root, 'private-key', $pvt_key ) if defined($pvt_key);
  $root-&gt;setAttribute( 'name', $name );

  if ($default) {
    $root-&gt;setAttribute('default', 'true');
  }

  $parent-&gt;getChild( 'certificates', 1 )-&gt;addChild($root);
}

sub addTemplateToServer {
  my ( $self, $templateType, $templateName, $dataPtr ) = @_;
  my %templates = (
    'reseller' =&gt; 'reseller-template',
    'domain' =&gt; 'domain-template',
    'domain_addon' =&gt; 'domain-template'
  );

  unless ( exists( $templates{$templateType} ) ){
    return;
  }

  $self-&gt;setServerSettings() unless defined $self-&gt;{serverNode};

  my $root = $self-&gt;{serverNode};
  my $node = $self-&gt;makeTemplateNode($templates{$templateType}, $templateName, $dataPtr);

  $root-&gt;getChild( 'account-templates', 1 )-&gt;addChild($node);

}

sub makePlanItemNode {
  my ( $self, $planItemPtr, $planItemPropsPtr, $customButtonsDir ) = @_;
  return unless ( ref($planItemPtr) =~ /HASH/ );
  return unless ( ref($planItemPropsPtr) =~ /HASH/ );

  return unless ( exists( $planItemPtr-&gt;{'name'}) &amp;&amp; exists( $planItemPtr-&gt;{'classname'}) &amp;&amp; exists( $planItemPtr-&gt;{'uuid'}) );

  my $planItemNode = XmlNode-&gt;new('plan-item');
  $planItemNode-&gt;setAttribute( 'name',    $planItemPtr-&gt;{'name'} );
  $planItemNode-&gt;setAttribute( 'type',    $planItemPtr-&gt;{'classname'} );
  $planItemNode-&gt;setAttribute( 'guid',    $planItemPtr-&gt;{'uuid'} );
  $planItemNode-&gt;setAttribute( 'visible', ($planItemPtr-&gt;{'isVisible'})? 'true' : 'false' );

  if ( ( $planItemPtr-&gt;{'classname'} eq 'Plan_Item_Custom') &amp;&amp; ( defined $planItemPropsPtr-&gt;{'file'} ) ) {
    my $file = $planItemPropsPtr-&gt;{'file'};
    my $filename = "$customButtonsDir/$file";
    if( -f $filename) {
      my $cid = $self-&gt;{content_transport}-&gt;addAdminContent('icon', undef, 'icon_planitem'.$planItemPtr-&gt;{'id'}, 'directory' =&gt; $customButtonsDir, 'include' =&gt; [$file]);
      $planItemNode-&gt;getChild('content', 1, 1)-&gt;addChild($cid) if $cid;
    }
  }
  my $applicableNode = XmlNode-&gt;new( 'applicable' );
  $applicableNode-&gt;addChild( XmlNode-&gt;new( 'applicable-to-subscription' ) ) if ( $planItemPtr-&gt;{'applicableToSubscription'} == 1 );
  $applicableNode-&gt;addChild( XmlNode-&gt;new( 'applicable-to-site'         ) ) if ( $planItemPtr-&gt;{'applicableToSite'        } == 1 );
  $applicableNode-&gt;addChild( XmlNode-&gt;new( 'applicable-to-email'        ) ) if ( $planItemPtr-&gt;{'applicableToEmail'       } == 1 );
  $planItemNode-&gt;addChild( $applicableNode );

  my $propertiesNode = XmlNode-&gt;new( 'properties' );
  while ( my ($name,$value) = each( %{$planItemPropsPtr} ) ) {
    next if ($name eq '');
    my $planItemPropertyNode = XmlNode-&gt;new( 'plan-item-property' );
    $planItemPropertyNode-&gt;setAttribute( 'name', $name);
    if ( $value ne '' ) {
      $planItemPropertyNode-&gt;setText( $value );
    }
    $propertiesNode-&gt;addChild( $planItemPropertyNode );
  }
  $planItemNode-&gt;addChild( $propertiesNode );

  return $planItemNode;
}

sub addPlanItemToServer {
  my ( $self, $planItemPtr, $planItemPropsPtr, $customButtonsDir ) = @_;
  my $root = $self-&gt;{serverNode};

  my $node = $self-&gt;makePlanItemNode( $planItemPtr, $planItemPropsPtr, $customButtonsDir );

  $root-&gt;getChild( 'account-templates', 1 )-&gt;addChild($node) if defined $node;
}

sub setServerSSO {
  my ( $self, $paramsPtr, $cert, $idpCert ) = @_;

  my %params = %{$paramsPtr};

  my $root = $self-&gt;{serverNode};

  my $ownership = defined $params{'admin_ownership'}
    &amp;&amp; $params{'admin_ownership'} eq 'true' ? 'true' : 'false';
  my $enabled = defined $params{'sso_enabled'}
    &amp;&amp; $params{'sso_enabled'} eq 'true' ? 'true' : 'false';

  my $ssoNode = XmlNode-&gt;new( 'sso-settings',
    'attributes' =&gt;  { 'enabled' =&gt; $enabled }  );

  my @settings = (
    'sso_server',         'sso_relay',
    'sso_application_id', 'sso_idp_api_version',
    'sso_idp_id'
  );

  my %settings_map = (
    'sso_server'          =&gt; 'sso-server',
    'sso_relay'           =&gt; 'sso-relay',
    'sso_application_id'  =&gt; 'sso-application-id',
    'sso_idp_api_version' =&gt; 'sso-idp-api-version',
    'sso_idp_id'          =&gt; 'sso-idp-id'
  );

  foreach my $setting (@settings) {
    $ssoNode-&gt;addChild(
      XmlNode-&gt;new(
        $settings_map{$setting}, 'content' =&gt; $params{$setting}
      )
    ) if ( defined $params{$setting} );
  }

  if ( $cert )
  {
    $ssoNode-&gt;addChild( XmlNode-&gt;new( 'sso-certificate', 'content' =&gt; $cert ) );
  }

  if ( $idpCert ) {
    $ssoNode-&gt;addChild(
      XmlNode-&gt;new( 'sso-idp-cert', 'content' =&gt; $idpCert ) );
  }

  $root-&gt;addChild($ssoNode);
}

sub setServerSSOBranding {
  my ( $self, $brandingPtr ) = @_;

  my @branding = @{$brandingPtr};

  my $root = $self-&gt;{serverNode};

  my @ssoNodes = $root-&gt;getChildren('sso-settings');
  if ( scalar(@ssoNodes) &lt; 1 ) {
    Logging::warning("Unable to dump SSO branding settings, because of dump XML structure is not full", 'PackerStructure');
    return;
  }
  my $ssoNode = $ssoNodes[0];

  my $ssoBrandingNode = XmlNode-&gt;new('sso-branding');
  if ( @branding ) {
    for my $ptrRow (@branding) {
      my $recordNode = XmlNode-&gt;new(
        'record',
        'children' =&gt; [
          XmlNode-&gt;new( 'idp-url', 'content' =&gt; $ptrRow-&gt;[1] ),
          XmlNode-&gt;new(
            'http-request-domain', 'content' =&gt; $ptrRow-&gt;[0]
          )
        ]
      );
      $ssoBrandingNode-&gt;addChild($recordNode);
    }
    $ssoNode-&gt;addChild($ssoBrandingNode);
  }
}

sub setServerAppVault {
  my ( $self ) = @_;

  my $root = $self-&gt;{serverNode};
  return $root-&gt;getChild('application-vault', 1);
}

sub setServerPackagesPool {
  my ( $self ) = @_;

  my $appVaultNode = $self-&gt;setServerAppVault();
  return $appVaultNode-&gt;getChild('sapp-packages-pool', 1);
}

my %dumpedApplications;

sub addServerAppPackage {
  my ($self, $name, $version, $release, $distrib_path, $file_name, $is_uploaded, $is_visible, $applicationPackage) = @_;

  my $fullname = $name."-".$version."-".$release;
  if (exists $dumpedApplications{$fullname}) {
        return;
  }

  $dumpedApplications{$fullname} = 1;

  my $appPackagesPoolNode = $self-&gt;setServerPackagesPool();

  my $packageNode = XmlNode-&gt;new('sapp-package');
  if ( defined $applicationPackage and $applicationPackage-&gt;getSappPackageId() ) {
      $packageNode-&gt;addChild(  XmlNode-&gt;new( 'sapp-package-id', 'content' =&gt; $applicationPackage-&gt;getSappPackageId() ) );
  }
  $packageNode-&gt;addChild(  XmlNode-&gt;new( 'sapp-name', 'content' =&gt; $name ) );
  $packageNode-&gt;addChild(  XmlNode-&gt;new( 'sapp-version', 'content' =&gt; $version ) )  if ( $version );
  $packageNode-&gt;addChild( XmlNode-&gt;new( 'sapp-release', 'content' =&gt; $release ) )  if ( $release );
  $packageNode-&gt;addChild( XmlNode-&gt;new( 'sapp-uploaded' ))  if ( defined $is_uploaded &amp;&amp; $is_uploaded ne "0" );
  $packageNode-&gt;addChild( XmlNode-&gt;new( 'sapp-visible' ))  if ( defined $is_visible &amp;&amp; $is_visible ne "0" );


  if( $distrib_path &amp;&amp; $file_name )
  {
    my $real_path = $distrib_path . "/" . $file_name;

    if ( -e $real_path ) {
      my $cid = $self-&gt;{content_transport}-&gt;addAdminContent(
        'sapp-distrib',
        undef,
        "sapp-distrib." . HelpFuncs::generateProcessId(),
        "directory" =&gt; $distrib_path,
        "include"   =&gt; [$file_name]
      );
      $packageNode-&gt;getChild( 'content', 1, 1 )-&gt;addChild( $cid ) if $cid;
    }
    else { return; }

    if ( defined $applicationPackage ) {
      my $settings = $applicationPackage-&gt;getSettings();
      if ( $settings ) {
        my $settingsNode = XmlNode-&gt;new('sapp-settings');
        foreach my $setting ( keys %{$settings} ) {
            my $settingNode = XmlNode-&gt;new('setting');
            $settingNode-&gt;addChild( XmlNode-&gt;new( 'name', 'content' =&gt; $setting ) );
            if (ref($settings-&gt;{$setting}) =~ /ARRAY/) {
              foreach my $value ( @{$settings-&gt;{$setting}}) {
                $settingNode-&gt;addChild( XmlNode-&gt;new( 'value', 'content' =&gt; $value ) );
              }
            } else {
              $settingNode-&gt;addChild( XmlNode-&gt;new( 'value', 'content' =&gt; $settings-&gt;{$setting} ) );
            }
            $settingsNode-&gt;addChild($settingNode);
        }
        $packageNode-&gt;addChild($settingsNode);
      }
    }

    $appPackagesPoolNode-&gt;addChild($packageNode);
  }
}

sub setServerAppItemsPool {
  my ( $self ) = @_;

  my $appVaultNode = $self-&gt;setServerAppVault();
  return $appVaultNode-&gt;getChild('sapp-items-pool',1);
}

sub addServerAppItem {
  my ($self, $paramsPtr) = @_;

  my %params = %{$paramsPtr};

  my $appItemsPoolNode = $self-&gt;setServerAppItemsPool();

  my $appItemNode = XmlNode-&gt;new('sapp-item');
  $appItemNode-&gt;setAttribute( 'enabled',
    ( $params{'disabled'} eq 'true' ) ? 'false' : 'true' )
    if defined $params{'disabled'};
  my $appSpecNode = XmlNode-&gt;new('sapp-spec');
  $appSpecNode-&gt;addChild(
    XmlNode-&gt;new( 'sapp-name', 'content' =&gt; $params{'sapp_name'} ) );
  $appSpecNode-&gt;addChild(
    XmlNode-&gt;new(
      'sapp-version', 'content' =&gt; $params{'sapp_version'}
    )
  ) if defined $params{'sapp_version'};
  $appSpecNode-&gt;addChild(
    XmlNode-&gt;new(
      'sapp-release', 'content' =&gt; $params{'sapp_release'}
    )
  ) if defined $params{'sapp_release'};
  $appItemNode-&gt;addChild($appSpecNode);
  $appItemNode-&gt;addChild(
    XmlNode-&gt;new(
      'license-type',
      'content' =&gt; defined( $params{'license_type_id'} )
      ? $params{'license_type_id'}
      : "0"
    )
  );
  $appItemNode-&gt;addChild(
    XmlNode-&gt;new( 'shared', 'content' =&gt; $params{'shared'} ) )
    if defined $params{'shared'};
  $appItemNode-&gt;addChild(
    XmlNode-&gt;new( 'description', 'content' =&gt; $params{'description'} )
  ) if defined $params{'description'};
  $appItemNode-&gt;addChild(
    XmlNode-&gt;new(
      'instances-limit', 'content' =&gt; $params{'instances_limit'}
    )
  ) if defined $params{'instances_limit'};

  $appItemsPoolNode-&gt;addChild($appItemNode);
}

sub setServerAppLicensesPool {
  my ( $self ) = @_;

  my $appVaultNode = $self-&gt;setServerAppVault();
  return $appVaultNode-&gt;getChild('sapp-licenses-pool',1);
}

sub addServerAppLicense {
  my ($self, $keyNumber, $licenseType, $licenseText) = @_;

  my $licensePoolNode = $self-&gt;setServerAppLicensesPool();

  my $licenseNode = XmlNode-&gt;new(
    'sapp-license',
    'children' =&gt; [
      XmlNode-&gt;new( 'key-number',   'content' =&gt; $keyNumber ),
      XmlNode-&gt;new( 'license-type', 'content' =&gt; $licenseType ),
      XmlNode-&gt;new( 'license-text', 'content' =&gt; $licenseText )
    ]
  );

  $licensePoolNode-&gt;addChild($licenseNode);
}

sub setServerSBConfig {
  my ( $self, $configPtr ) = @_;

  my @config = @{$configPtr};

  my $serverNode = $self-&gt;{serverNode};

  my $sbNode = XmlNode-&gt;new('sb-config');
  for my $ptrHash (@config) {
    $sbNode-&gt;addChild(
      XmlNode-&gt;new(
        'sb-param',
        'children' =&gt; [
          XmlNode-&gt;new(
            'sb-param-name', 'content' =&gt; $ptrHash-&gt;{'param_name'}
          ),
          XmlNode-&gt;new(
            'sb-param-value', 'content' =&gt; $ptrHash-&gt;{'param_value'}
          )
        ]
      )
    );
  }
  $serverNode-&gt;addChild($sbNode);
}

sub setGLServerSettings {
  my ( $self, $paramsPtr) = @_;

  my %params = %{$paramsPtr};

  my $serverNode = $self-&gt;{serverNode};

  my $glNode = XmlNode-&gt;new('grey-listing');

  $glNode-&gt;setAttribute('grey-interval', $params{'greyInterval'}) if defined $params{'greyInterval'};
  $glNode-&gt;setAttribute('expire-interval', $params{'expireInterval'}) if defined $params{'expireInterval'};
  $glNode-&gt;setAttribute('penalty-enabled', $params{'penaltyEnabled'}) if defined $params{'penaltyEnabled'};
  $glNode-&gt;setAttribute('penalty-interval', $params{'penaltyInterval'}) if defined $params{'penaltyInterval'};
  $glNode-&gt;setAttribute('enabled', $params{'enabled'}) if defined $params{'enabled'};
  $glNode-&gt;setAttribute('personal-conf', $params{'personal-conf'}) if defined $params{'personal-conf'};

  my $wlNode = XmlNode-&gt;new('white-list');

  foreach my $wdomain (@{$params{'white_domains'}}) {
        $wlNode-&gt;addChild(XmlNode-&gt;new('list-item', 'content' =&gt; $wdomain));
  }

  $glNode-&gt;addChild($wlNode);

  my $blNode = XmlNode-&gt;new('black-list');

  foreach my $bdomain (@{$params{'black_domains'}}) {
        $blNode-&gt;addChild(XmlNode-&gt;new('list-item', 'content' =&gt; $bdomain));
  }

  $glNode-&gt;addChild($blNode);

  $serverNode-&gt;addChild($glNode);

}

sub setControlsVisibility {
  my ( $self, $paramsPtr ) = @_;

  my %params = %{$paramsPtr};

  my $serverNode = $self-&gt;{serverNode};
  my $controlsVisibilityNode = XmlNode-&gt;new('controls-visibility');

  $controlsVisibilityNode-&gt;addChild( XmlNode-&gt;new( 'hide-domain-registration-buttons', 'content' =&gt; HelpFuncs::negation(HelpFuncs::checkValue($params{'domain_registration'},'true','false')) ) );
  $controlsVisibilityNode-&gt;addChild( XmlNode-&gt;new( 'hide-certificate-purchasing-buttons', 'content' =&gt; HelpFuncs::negation(HelpFuncs::checkValue($params{'cert_purchasing'},'true','false')) ) );
  $controlsVisibilityNode-&gt;addChild( XmlNode-&gt;new( 'hide-extra-services-buttons', 'content' =&gt; HelpFuncs::negation(HelpFuncs::checkValue($params{'extras'},'true','false')) ) );
  $controlsVisibilityNode-&gt;addChild( XmlNode-&gt;new( 'hide-mail-bouncing-controls', 'content' =&gt; HelpFuncs::negation(HelpFuncs::checkValue($params{'mail_bounce'},'true','false')) ) );

  $controlsVisibilityNode-&gt;addChild( XmlNode-&gt;new( 'domain-registration-url', 'content' =&gt; $params{'domain_registration_url'})) if defined $params{'domain_registration_url'};
  $controlsVisibilityNode-&gt;addChild( XmlNode-&gt;new( 'domain-management-url', 'content' =&gt; $params{'domain_management_url'})) if defined $params{'domain_management_url'};
  $controlsVisibilityNode-&gt;addChild( XmlNode-&gt;new( 'cert-purchasing-url', 'content' =&gt; $params{'cert_purchasing_url'})) if defined $params{'cert_purchasing_url'};
  $controlsVisibilityNode-&gt;addChild( XmlNode-&gt;new( 'mpc-portal-url', 'content' =&gt; $params{'mpc_portal_url'})) if defined $params{'mpc_portal_url'};

  $serverNode-&gt;getChild( 'interface-preferences', 1 )-&gt;addChild($controlsVisibilityNode);
}

sub setServerBackupSettings {
  my ( $self, $paramsPtr ) = @_;

  my %params = %{$paramsPtr};

  my $serverNode = $self-&gt;{serverNode};

  my ($lowPriority,$doNotCompress,$maxProcesses);

  $lowPriority = $params{'bu_nice'};
  $doNotCompress = $params{'bu_nozip'};
  $maxProcesses = $params{'max_bu_proc_number'};

  if ( defined $lowPriority or defined $doNotCompress or defined $maxProcesses ) {
  	my $serverBackupSettingsNode = XmlNode-&gt;new('backup-settings');

  	$serverBackupSettingsNode-&gt;setAttribute( 'low-priority', $lowPriority)
			if defined $lowPriority and $lowPriority eq 'true';

  	$serverBackupSettingsNode-&gt;setAttribute( 'do-not-compress', $doNotCompress)
			if defined $doNotCompress and $doNotCompress eq 'true';

		$serverBackupSettingsNode-&gt;setAttribute( 'max-processes', $maxProcesses)
  		if defined $maxProcesses;

  	$serverNode-&gt;addChild($serverBackupSettingsNode);
  }
}

sub addServerPreferences {
  my ( $self, $paramsPtr ) = @_;

  my %params = %{$paramsPtr};

  my $serverNode = $self-&gt;{serverNode};

  my $serverPrefsNode = XmlNode-&gt;new('server-preferences');

  if ( defined $params{'forbid_create_dns_subzone'} ) {
    $serverPrefsNode-&gt;addChild(
      XmlNode-&gt;new(
        'forbid-create-dns-subzone',
        'content' =&gt; $params{'forbid_create_dns_subzone'}
      )
    );
  }
  if ( defined $params{'force_db_user_prefix'} ) {
    $serverPrefsNode-&gt;addChild(
      XmlNode-&gt;new(
        'force-db-user-prefix',
        'content' =&gt; $params{'force_db_user_prefix'}
      )
    );
  }

  if ( defined $params{'db_user_length'} ) {
    $serverPrefsNode-&gt;addChild(
      XmlNode-&gt;new(
        'db-user-length', 'content' =&gt; $params{'db_user_length'}
      )
    );
  }

  if ( defined $params{'hide_top_advertisement'} ) {
    $serverPrefsNode-&gt;addChild(
      XmlNode-&gt;new(
        'hide-top-advertisement',
        'attributes' =&gt; { 'hide' =&gt; $params{'hide_top_advertisement'} }
      )
    );
  }
  if ( defined $params{'traffic_accounting'} ) {
    my $val = $params{'traffic_accounting'};
    if    ( $val == 1 ) { $val = 'in'; }
    elsif ( $val == 2 ) { $val = 'out'; }
    else                { $val = 'both'; }
    $serverPrefsNode-&gt;addChild(
      XmlNode-&gt;new(
        'traffic-direction', 'attributes' =&gt; { 'traffic' =&gt; $val }
      )
    );
  }
  if ( defined $params{'restart_apache_interval'} ) {
    $serverPrefsNode-&gt;addChild(
      XmlNode-&gt;new(
        'restart-apache', 'content' =&gt; $params{'restart_apache_interval'}
      )
    );
  }
  if ( defined $params{'stat_ttl'} ) {
    $serverPrefsNode-&gt;addChild(
      XmlNode-&gt;new( 'stat-keep', 'content' =&gt; $params{'stat_ttl'} ) );
  }
  if ( defined $params{'size_count_type'} ) {
    $serverPrefsNode-&gt;addChild(
      XmlNode-&gt;new(
        'disk-space-count-type',
        'attributes' =&gt; {
            'count-type' =&gt; $params{'size_count_type'} eq 'byte'
          ? 'byte'
          : 'block'
        }
      )
    );
  }

  my $duNode = XmlNode-&gt;new('disk-usage');
  $serverPrefsNode-&gt;addChild($duNode);
  $duNode-&gt;addChild( XmlNode-&gt;new('include-logs') )
    if defined $params{'include_logs'}
      and $params{'include_logs'} eq 'true';
  $duNode-&gt;addChild( XmlNode-&gt;new('include-databases') )
    if defined $params{'include_databases'}
      and $params{'include_databases'} eq 'true';
  $duNode-&gt;addChild( XmlNode-&gt;new('include-mailboxes') )
    if defined $params{'include_mailboxes'}
      and $params{'include_mailboxes'} eq 'true';
  $duNode-&gt;addChild( XmlNode-&gt;new('include-webapps') )
    if defined $params{'include_webapps'}
      and $params{'include_webapps'} eq 'true';
  $duNode-&gt;addChild( XmlNode-&gt;new('include-maillists') )
    if defined $params{'include_maillists'}
      and $params{'include_maillists'} eq 'true';
  $duNode-&gt;addChild( XmlNode-&gt;new('include-domaindumps') )
    if defined $params{'include_domaindumps'}
      and $params{'include_domaindumps'} eq 'true';
  $duNode-&gt;addChild( XmlNode-&gt;new('include-admindumps') )
    if defined $params{'include_admindumps'}
      and $params{'include_admindumps'} eq 'true';

  $serverPrefsNode-&gt;addChild( XmlNode-&gt;new( 'force-db-prefix', 'content' =&gt; $params{'force_db_prefix'} ) ) if defined $params{'force_db_prefix'};
  $serverPrefsNode-&gt;addChild( XmlNode-&gt;new( 'multiple-session', 'content' =&gt; $params{'multiply_login'} ) ) if defined $params{'multiply_login'};
  $serverPrefsNode-&gt;addChild( XmlNode-&gt;new( 'lock-screen', 'content' =&gt; ($params{'disable_lock_screen'} eq 'true' ? 'false' : 'true' ) ) ) if defined $params{'disable_lock_screen'};

  $serverPrefsNode-&gt;addChild( XmlNode-&gt;new( 'aps-catalog-url', 'content' =&gt; $params{'apscatalog_url'} ) ) if defined $params{'apscatalog_url'};

  $serverPrefsNode-&gt;addChild( XmlNode-&gt;new( 'mode', 'content' =&gt; (defined($params{'power_user_panel'}) and $params{'power_user_panel'} eq 'true') ? 'poweruser' : 'standard'));

  $serverNode-&gt;addChild($serverPrefsNode);
}

sub addServerMailmanConfiguration {
  my ($self) = @_;

  unless ( defined Mailman::version() ) {
    Logging::debug("Unable to found Mailman installation");
    return;
  }

  if (Mailman::isMailmanNotConfigured() eq '1') {
    Logging::debug("Mailman is not configured. Nothing to backup");
    return;
  }

  my $adminPassword =  Mailman::getListPassword('mailman');
  my @owners = Mailman::getListOwners('mailman');

  if (defined $adminPassword and defined $owners[0]) {
    my $root = $self-&gt;{serverNode};

    my $mailmanNode = XmlNode-&gt;new('mailman');

    $mailmanNode-&gt;setAttribute('owner', $owners[0]);
    $mailmanNode-&gt;setAttribute('password', $adminPassword);

    $root-&gt;addChild($mailmanNode);
  }
}

sub addDisableMailUiOption {
  my ($self, $state) = @_;
  my $serverNode = $self-&gt;{serverNode};
  my $serverPrefNode = $serverNode-&gt;getChild( 'server-preferences', 1 );
  my $disableUiNode = XmlNode-&gt;new('disable-mail-ui', 'content' =&gt; $state);
  $serverPrefNode-&gt;addChild($disableUiNode);
}

sub _makeExternalWebmails {
  my ($self, $webmailsPtr) = @_;
  my $serverNode = $self-&gt;{serverNode};
  my $mailPrefNode = $serverNode-&gt;getChild( 'mail-settings', 1 );
  my @webmails = @{$webmailsPtr};

  foreach my $webmail (@webmails) {
    my $extWebMailNode = XmlNode-&gt;new('external-webmail');
    $extWebMailNode-&gt;addChild( XmlNode-&gt;new('name', 'content' =&gt; $webmail-&gt;{'name'}) );
    $extWebMailNode-&gt;addChild( XmlNode-&gt;new('url', 'content' =&gt; $webmail-&gt;{'url'}) );
    $extWebMailNode-&gt;addChild( XmlNode-&gt;new('enabled') ) if $webmail-&gt;{'enabled'} == 1;
    $mailPrefNode-&gt;addChild($extWebMailNode);
  }
}

sub addRestrictionItem {
  my ( $self, $type, $ip, $mask ) = @_;

  $ip = '' unless defined $ip;
  $mask = '' unless defined $mask;

  my $serverNode = $self-&gt;{serverNode};

  my $serverPrefNode = $serverNode-&gt;getChild( 'server-preferences', 1 );

  my $adminAccessRestrictionsNode = $serverPrefNode-&gt;getChild( 'admin-access-restrictions', 1 );

  my $restrictionItemNode = XmlNode-&gt;new( 'restriction-item' );
  $restrictionItemNode-&gt;setAttribute( 'type', $type eq 'allow'? 'allow' : 'deny' );
  $restrictionItemNode-&gt;setAttribute( 'ip-address', $ip );
  $restrictionItemNode-&gt;setAttribute( 'ip-subnet-mask', $mask );

  $adminAccessRestrictionsNode-&gt;addChild( $restrictionItemNode );
}

sub addRootAdmin {
  my ( $self, $id, $guid ) = @_;

  return if defined $self-&gt;{admin};

  my $rootNode = $self-&gt;{root};
  if ( !defined($rootNode) ) {
    Logging::warning('Unable to dump Panel admin user, because of dump XML structure is not full', 'PackerStructure');
    return;
  }
  my $root = XmlNode-&gt;new( 'admin' );
  $self-&gt;{admin} = $root;
  $root-&gt;setAttribute( 'id', $id ) if $id;
  $root-&gt;setAttribute( 'guid', $guid ) if $guid;

  $rootNode-&gt;addChild($root);
}

### Client functions ##

sub addRootClient {
  my ( $self, $clientId, $clientPtr, $passwdPtr, $status ) = @_;

  my $rootNode = $self-&gt;{root};
  if ( !defined($rootNode) ) {
    Logging::warning('Unable to dump root client user, because of dump XML structure is not full', 'PackerStructure');
    return;
  }

  my $root = $self-&gt;makeClientNode($clientId, $clientPtr, $passwdPtr, $status, 1);

  $rootNode-&gt;addChild($root);
  push @{$self-&gt;{roots}}, $root;
}

sub addRootReseller{
  my ( $self, $clientId, $clientPtr, $passwdPtr, $status ) = @_;

  my $rootNode = $self-&gt;{root};
  if ( !defined($rootNode) ) {
    Logging::warning('Unable to dump reseller, because of dump XML structure is not full', 'PackerStructure');
    return;
  }

  my $root = $self-&gt;makeResellerNode($clientId, $clientPtr, $passwdPtr, $status, 1);

  $rootNode-&gt;addChild($root);
  push @{$self-&gt;{roots}}, $root;
}

sub addResellerClient {
  my ( $self, $resellerId, $clientId, $clientPtr, $passwdPtr, $status ) = @_;

  my %client = %{$clientPtr};
  my %passwd = %{$passwdPtr};

  my $resellerNode = $self-&gt;{resellersNodes}-&gt;{$resellerId};
  if (!defined($resellerNode))
  {
    Logging::warning('Unable to dump reseller\'s client, because of dump XML structure is not full', 'PackerStructure');
    return;
  }

  my $root = $self-&gt;makeClientNode($clientId, \%client, \%passwd, $status, 0);

  $resellerNode-&gt;getChild( 'clients', 1 )-&gt;addChild($root);
  $self-&gt;regClientObjectBackupPath( $self-&gt;getResellersBackupPath( $resellerId ), $clientId, $clientPtr-&gt;{'login'} );

  if (exists $self-&gt;{resellersShortNodes}-&gt;{$resellerId}) {
    $self-&gt;{resellersShortNodes}-&gt;{$resellerId}-&gt;addChild($self-&gt;{clientsShortNodes}-&gt;{$clientId});
  }
}

sub addAdminClient {
  my ( $self, $clientId, $clientPtr, $passwdPtr, $status ) = @_;

  my %client = %{$clientPtr};
  my %passwd = %{$passwdPtr};

  my $admin = $self-&gt;{admin};
  if (!defined($admin))
  {
    Logging::warning('Unable to dump admin\'s client, because of dump XML structure is not full', 'PackerStructure');
    return;
  }

  my $root = $self-&gt;makeClientNode($clientId, \%client, \%passwd, $status, 0);

  $admin-&gt;getChild( 'clients', 1 )-&gt;addChild($root);
  $self-&gt;regClientObjectBackupPath( $self-&gt;getAdminBackupPath(), $clientId, $clientPtr-&gt;{'login'} );
}

sub addAdminReseller {
  my ( $self, $clientId, $clientPtr, $passwdPtr, $status ) = @_;

  my $admin = $self-&gt;{admin};
  if (!defined($admin))
  {
    Logging::warning('Unable to dump admin\'s reseller, because of dump XML structure is not full', 'PackerStructure');
    return;
  }

  my $root = $self-&gt;makeResellerNode($clientId, $clientPtr, $passwdPtr, $status, 0);

  $admin-&gt;getChild( 'resellers', 1 )-&gt;addChild($root);
  $self-&gt;regResellersObjectBackupPath( $self-&gt;getAdminBackupPath(), $clientId, $clientPtr-&gt;{'login'} );
}

sub makeResellerNode{
  my ( $self, $clientId, $clientPtr, $passwdPtr, $status, $needFullInfo ) = @_;

  my $root = $self-&gt;processClientNode( $clientId, $clientPtr, $passwdPtr, $status, 1, $needFullInfo );

  return $root;

}

sub makeClientNode {
  my ( $self, $clientId, $clientPtr, $passwdPtr, $status, $needFullInfo ) = @_;

  my $root = $self-&gt;processClientNode( $clientId, $clientPtr, $passwdPtr, $status, 0, $needFullInfo );

  return $root;
}

sub processClientNode {
  my ( $self, $clientId, $clientPtr, $passwdPtr, $status, $is_reseller, $needFullInfo ) = @_;

  my $root = XmlNode-&gt;new( $is_reseller ? 'reseller' : 'client');

  $root-&gt;getChild( 'preferences', 1 );
  $root-&gt;getChild( 'properties', 1 );

  my %client = %{$clientPtr};
  my %passwd = %{$passwdPtr};

  $root-&gt;setAttribute( 'id', $clientId );

  if ( defined $client{'uid'} ) {
    $root-&gt;setAttribute( 'uid', $client{'uid'} );
    $root-&gt;setAttribute( 'ownership', $client{'ownership'} eq 'true' ? 'true' : 'false' );
  }

  $root-&gt;setAttribute( 'guid', $client{'guid'} ) if ( defined $client{'guid'} );

  $root-&gt;setAttribute( 'external-id', $client{'external_id'} ) if ( defined $client{'external_id'} and $client{'external_id'} ne '');

  $root-&gt;setAttribute( 'vendor-guid', $client{'vendor-guid'} ) if ( defined $client{'vendor-guid'} );

  $root-&gt;setAttribute( 'vendor-login', $client{'vendor-login'} ) if ( defined $client{'vendor-login'} );

  $root-&gt;setAttribute( 'owner-guid', $client{'owner-guid'} ) if ( defined $client{'owner-guid'} and not $is_reseller );

  if ( exists $client{'login'} ) {
    $root-&gt;setAttribute( 'name', ( defined $client{'login'} )? $client{'login'}:'' );
  }
  if ( exists $client{'pname'} ) {
    $root-&gt;setAttribute( 'contact', ( defined $client{'pname'} )? $client{'pname'}:'' );
  }
  if ( exists $client{'cr_date'} ) {
    $root-&gt;setAttribute( 'cr-date', ( defined $client{'cr_date'} )? $client{'cr_date'}:'' );
  }
  if ( exists $client{'owner-name'} and not $is_reseller ) {
    $root-&gt;setAttribute( 'owner-name', $client{'owner-name'} );
  }

  my $item;
  my $props = $root-&gt;getChild( 'properties', 1 );
  $item = CommonPacker::makePasswordNode( $passwd{'password'}, CommonPacker::normalizePasswordType( $passwd{'type'} ) );
  $props-&gt;addChild($item);

  $props-&gt;addChild( Status::make($status) );

  $self-&gt;{clientNodes}-&gt;{$clientId} = $root;
  $self-&gt;{resellersNodes}-&gt;{$clientId} = $root if $is_reseller;

  if ($needFullInfo) {
    return $root;
  } else {
    my $shortInfoNodeName = ($is_reseller ? 'reseller' : 'client') . '-info';
    my $shortInfoNode = XmlNode-&gt;new($shortInfoNodeName);
    $shortInfoNode-&gt;setAttribute('name', ( defined $client{'login'} )? $client{'login'}:'');
    $shortInfoNode-&gt;setAttribute( 'guid', $client{'guid'} ) if defined $client{'guid'};
    if ($is_reseller) {
      $self-&gt;{resellersShortNodes}-&gt;{$clientId} = $shortInfoNode;
    } else {
      $self-&gt;{clientsShortNodes}-&gt;{$clientId} = $shortInfoNode;
    }
    return $shortInfoNode;
  }

}

sub finishClient {
  my ( $self, $clientId ) = @_;

  my $root = $self-&gt;{clientNodes}-&gt;{$clientId};
  if ( !defined($root) ) {
    Logging::warning('Unable to finish client node, because of dump XML structure is not full', 'PackerStructure');
    return;
  }

  #TODO: uncomment
  #$root-&gt;ReleaseCode();
}

sub setClientPinfo {
  my ( $self, $clientId, $clientPtr ) = @_;

  my %client = %{$clientPtr};

  my $root = $self-&gt;{clientNodes}-&gt;{$clientId};
  if ( !defined($root) ) {
    Logging::warning('Unable to dump client personal information, because of dump XML structure is not full', 'PackerStructure');
    return;
  }

  my ( $field, $name );

  my %clientsInfo = (
    'company' =&gt; 'cname',
    'phone'   =&gt; 'phone',
    'fax'     =&gt; 'fax',
    'address' =&gt; 'address',
    'city'    =&gt; 'city',
    'state'   =&gt; 'state',
    'zip'     =&gt; 'pcode',
    'country' =&gt; 'country',
    'email'   =&gt; 'email',
  );
  my $prefs = $root-&gt;getChild( 'preferences', 1 );
  while ( ( $name, $field ) = each(%clientsInfo) ) {
    if ( exists( $client{$field} ) &amp;&amp; $client{$field} ) {
      $prefs-&gt;addChild(
        XmlNode-&gt;new(
          'pinfo',
          'content'    =&gt; $client{$field},
          'attributes' =&gt; { 'name' =&gt; $name }
        )
      );
    }
  }
}

sub setClientLocale {
  my ( $self, $clientId, $locale ) = @_;

  my $root = $self-&gt;{clientNodes}-&gt;{$clientId};
  if ( !defined($root) ) {
    Logging::warning('Unable to dump client locale, because of dump XML structure is not full', 'PackerStructure');
    return;
  }

  $root-&gt;getChild( 'preferences', 1 )-&gt;addChild(
    XmlNode-&gt;new(
      'pinfo',
      'content'    =&gt; $locale,
      'attributes' =&gt; { 'name' =&gt; 'locale' }
    )
  );
}

sub addClientLimit {
  my ( $self, $clientId, $name, $value ) = @_;

  my $root = $self-&gt;{clientNodes}-&gt;{$clientId};
  if ( !defined($root) ) {
    Logging::warning('Unable to dump client limits, because of dump XML structure is not full', 'PackerStructure');
    return;
  }

  $self-&gt;insertLimitNode( $root, $name, $value );
}

sub addClientPermission {
  my ( $self, $clientId, $name, $value ) = @_;

  my $root = $self-&gt;{clientNodes}-&gt;{$clientId};
  if ( !defined($root) ) {
    Logging::warning('Unable to dump client permissions, because of dump XML structure is not full', 'PackerStructure');
    return;
  }

  $self-&gt;makePermissionNode( $root-&gt;getChild( 'limits-and-permissions', 1 ), $name, $value );
}

sub addClientDomainSkeleton {
  my ( $self, $clientId, $path, $arc_path ) = @_;

  my $root = $self-&gt;{clientNodes}-&gt;{$clientId};
  if ( !defined($root) ) {
    Logging::warning('Unable to dump client\'s domain skeleton, because of dump XML structure is not full', 'PackerStructure');
    return;
  }

  my $dumpFile = $self-&gt;{content_transport}-&gt;addClientContent( 'skeleton', $clientId, $arc_path, 'directory' =&gt; $path );
  $root-&gt;getChild( 'content', 1, 1 )-&gt;addChild( $dumpFile) if $dumpFile;
}

sub addServerSkeleton {
  my ( $self, $path, $arc_path) = @_;

  my $root = $self-&gt;{serverNode};

  my $dumpFile = $self-&gt;{content_transport}-&gt;addAdminContent('skeleton', undef, $arc_path, 'directory' =&gt; $path);

  $root-&gt;getChild('content', 1, 1)-&gt;addChild($dumpFile) if $dumpFile;
}

sub addSmbDbDump {
  my ($self, $options) = @_;
  my $root = $self-&gt;{serverNode};
  $options-&gt;{utf8names} = 1;
  my $cid = $self-&gt;{content_transport}-&gt;addDbContent('smb-sqldump', $self-&gt;getAdminBackupPath('smbdb'), %{$options});
  $root-&gt;getChild('content', 1, 1)-&gt;addChild($cid) if $cid;
}

sub addApsCache {
  my ($self, $path) = @_;
  my $root = $self-&gt;{serverNode};
  my $dumpFile = $self-&gt;{content_transport}-&gt;addAdminContent('aps-cache', undef, 'aps_cache', 'directory' =&gt; $path, 'checkEmptyDir' =&gt; 1 );
  $root-&gt;getChild('content', 1, 1)-&gt;addChild($dumpFile) if $dumpFile;
}

sub addResellerDomainsClientsNodes {
  my ( $self, $clientId ) = @_;

  my $root = $self-&gt;{clientNodes}-&gt;{$clientId};
  if ( !defined($root) ) {
    Logging::warning('Unable to dump reseller\'s clients and domains, because of dump XML structure is not full', 'PackerStructure');
    return;
  }
  $root-&gt;addChild( XmlNode-&gt;new('domains') );
  $root-&gt;addChild( XmlNode-&gt;new('clients') );
}

sub removeSiteNode {
  my ( $self, $domainId, $siteName ) = @_;

  my $domainNode = $self-&gt;{domainNodes}-&gt;{$domainId};
  my $sitesNode = $domainNode-&gt;getChild( 'phosting' )-&gt;getChild( 'sites' );

  if ( defined $sitesNode ) {
    $sitesNode-&gt;removeChildByAttribute( 'site', 'name', $siteName );
  }
}

sub removeDatabaseNode {
  my ( $self, $domainId, $db ) = @_;
  my $domainNode = $self-&gt;{domainNodes}-&gt;{$domainId};
  my $dbNode = $domainNode-&gt;getChild( 'databases' );
  if ( defined $dbNode ) {
    $dbNode-&gt;removeChildByAttribute( 'database', 'id', $db-&gt;{'id'} );
  }
}

sub removeServerNode {
  my ( $self ) = @_;
  $self-&gt;{serverNode} = undef;
}

sub removeMailuserNode {
  my ( $self, $domainId, $mail ) = @_;
  my $domainNode = $self-&gt;{domainNodes}-&gt;{$domainId};
  my $mailSystemNode = $domainNode-&gt;getChild( 'mailsystem' );
  my $mailUsersNode = $mailSystemNode-&gt;getChild( 'mailusers' );

  if ( defined $mailUsersNode ) {
    $mailUsersNode-&gt;removeChildByAttribute( 'mailuser', 'id', $mail-&gt;{'id'} );
  }
}

sub removeMailSystemNode {
  my ( $self, $domainId ) = @_;
  my $domainNode = $self-&gt;{domainNodes}-&gt;{$domainId};
  $domainNode-&gt;removeChildren( 'mailsystem' );
}

sub removeHostingNode {
  my ( $self, $domainId, $hostingType ) = @_;
  my $domainNode = $self-&gt;{domainNodes}-&gt;{$domainId};
  my $hostingNodeName;
  if ( $hostingType eq 'vrt_hst' )  {
    $hostingNodeName = 'phosting';
  } elsif ( $hostingType eq 'std_fwd' ) {
    $hostingNodeName = 'shosting';
  } elsif ( $hostingType eq 'frm_fwd' ) {
    $hostingNodeName = 'fhosting';
  }
  $domainNode-&gt;removeChildren( $hostingNodeName );
}

sub addClientIps {
  my ( $self, $clientId, $ipsPtr ) = @_;

  my %ips = %{$ipsPtr};

  my $root = $self-&gt;{clientNodes}-&gt;{$clientId};
  if ( !defined($root) ) {
    Logging::warning('Unable to dump client\'s IP settings, because of dump XML structure is not full', 'PackerStructure');
    return;
  }

  my $ip_pool = XmlNode-&gt;new('ip_pool');
  $root-&gt;addChild($ip_pool);

  while( my($ip,$iptype) = each(%ips) ){
   $ip_pool-&gt;addChild( $self-&gt;makeIpNode($ip, $iptype) );
  }
}

sub setClientTraffic{
  my ( $self, $clientId, $trafficValue ) = @_;

  my $parent = $self-&gt;{clientNodes}-&gt;{$clientId};
  if ( !defined($parent) ) {
    Logging::warning('Unable to dump client traffic, because of dump XML structure is not full', 'PackerStructure');
    return;
  }

  $parent-&gt;addChild( XmlNode-&gt;new( 'traffic', 'content' =&gt; $trafficValue ) );
}

sub addResellerDomainTemplate {
  my $self = shift;
  $self-&gt;addClientDomainTemplate( @_ );
}

sub addClientDomainTemplate {
  my ( $self, $clientId, $templateName, $dataPtr ) = @_;

  my $root = $self-&gt;{clientNodes}-&gt;{$clientId};

  my $node = $self-&gt;makeTemplateNode('domain-template', $templateName, $dataPtr);

  $root-&gt;getChild( 'preferences', 1 )-&gt;addChild($node);
}

sub addClientCustomButton {
    my ( $self, $clientId, $id, $optionsPtr, $customButtonsDir, $icon ) = @_;

    my $parent = $self-&gt;{clientNodes}-&gt;{$clientId};
    if ( !defined($parent) ) {
      Logging::warning('Unable to dump client\'s custom buttons settings, because of dump XML structure is not full', 'PackerStructure');
      return;
    }

    my $node = $self-&gt;makeCustomButtonNode( 'clients', $clientId, $id, $optionsPtr, $customButtonsDir,
      $icon );

    $parent-&gt;getChild( 'preferences', 1 )-&gt;addChild($node);
}

sub setPpbConnection {
    my ($self, $clientParams) = @_;

    my $ppbUrl = undef;
    my $apiVersion = undef;

    my $parent;

    $parent = $self-&gt;{serverNode};

    $ppbUrl = $clientParams-&gt;{'ppb-url'} if exists $clientParams-&gt;{'ppb-url'};

    if (defined $ppbUrl &amp;&amp; defined $apiVersion) {
        my $ppbConnectionNode = XmlNode-&gt;new('ppb-connection');
        $ppbConnectionNode-&gt;addChild(XmlNode-&gt;new('ppb-url', 'content' =&gt; $ppbUrl));
        $parent-&gt;getChild( 'properties', 1)-&gt;addChild($ppbConnectionNode);
    }
}

### Domain functions ##
my @_rootDomains;

sub addRootDomain {
  my ( $self, $domainId, $domainName, $domainAsciiName, $domainPtr, $ownerGuid ) = @_;
  $domainAsciiName = $domainName if not $domainAsciiName;

  my $root = $self-&gt;makeDomainNode($domainId, $domainName, $domainPtr, 0, 1);
  push @_rootDomains, $root;
}

sub addRootDomains {
  my $self = shift;

  my $rootNode = $self-&gt;{root};
  if ( !defined($rootNode) ) {
    Logging::warning('Unable to dump root domains, because of dump XML structure is not full', 'PackerStructure');
    return;
  }

  for my $domainNode ( @_rootDomains ) {
    $rootNode-&gt;addChild($domainNode);
    push @{$self-&gt;{roots}}, $domainNode;
  }
}

sub addAdminDomain {
    my ( $self, $domainId, $domainName, $domainAsciiName, $domainPtr ) = @_;
    $domainAsciiName = $domainName if not $domainAsciiName;

    my $admin = $self-&gt;{admin};
    if ( !defined($admin) ) {
      Logging::warning('Unable to dump admin\'s domain, because of dump XML structure is not full', 'PackerStructure');
      return;
    }

    my $root = $self-&gt;makeDomainNode($domainId, $domainName, $domainPtr, 0, 0);

    $admin-&gt;getChild( 'domains', 1 )-&gt;addChild($root);
    $self-&gt;regDomainObjectBackupPath( $self-&gt;getAdminBackupPath(), $domainId, $domainAsciiName );

}

sub addResellerDomain {
    my ( $self, $resellerId, $domainId, $domainName, $domainAsciiName, $domainPtr ) = @_;
    $domainAsciiName = $domainName if not $domainAsciiName;

    my $resellerNode = $self-&gt;getCashedClientNode($resellerId);
    return unless defined $resellerNode;

    my $root = $self-&gt;makeDomainNode($domainId, $domainName, $domainPtr, 0, 0);

    $resellerNode-&gt;getChild( 'domains', 1 )-&gt;addChild($root);
    $self-&gt;regDomainObjectBackupPath( $self-&gt;getResellersBackupPath( $resellerId ), $domainId, $domainAsciiName );

    if (exists $self-&gt;{resellersShortNodes}-&gt;{$resellerId}) {
      $self-&gt;{resellersShortNodes}-&gt;{$resellerId}-&gt;addChild($self-&gt;{domainShortNodes}-&gt;{$domainId});
    }
}

sub addClientDomain {
    my ( $self, $clientId, $domainId, $domainName, $domainAsciiName, $domainPtr ) = @_;
    $domainAsciiName = $domainName if not $domainAsciiName;

    my $clientNode = $self-&gt;getCashedClientNode($clientId);
    return unless defined $clientNode;

    my $root = $self-&gt;makeDomainNode($domainId, $domainName, $domainPtr, 0, 0);

    $clientNode-&gt;getChild( 'domains', 1 )-&gt;addChild($root);
    $self-&gt;regDomainObjectBackupPath( $self-&gt;getClientsBackupPath( $clientId ), $domainId, $domainAsciiName );

    if (exists $self-&gt;{clientsShortNodes}-&gt;{$clientId}) {
      $self-&gt;{clientsShortNodes}-&gt;{$clientId}-&gt;addChild($self-&gt;{domainShortNodes}-&gt;{$domainId});
    }
}

my %_rootUsers;
my %_rootRoles;

sub addDomainSite {
    my ( $self, $domainId, $siteId, $siteAsciiName, $siteName, $sitePtr ) = @_;

    my $domainNode = $self-&gt;{domainNodes}-&gt;{$domainId};
    if ( !defined($domainNode) ) {
      Logging::warning('Unable to dump domain site, because of dump XML structure is not full', 'PackerStructure');
      return;
    }

    my $siteNode = $self-&gt;makeDomainNode($siteId, $siteName, $sitePtr, 1, 1);
    my $phostingNode = $domainNode-&gt;getChild( 'phosting', 1 );
    $phostingNode-&gt;getChild( 'sites', 1 )-&gt;addChild($siteNode);
    $self-&gt;regSiteObjectBackupPath( $self-&gt;getDomainsBackupPath( $domainId ), $siteId, $siteAsciiName );
}

sub addAdminUser {
  my ( $self, $userName, $userPtr ) = @_;

  my $adminNode = $self-&gt;{admin};
  if ( !defined($adminNode) ) {
    Logging::warning('Unable to dump admin user, because of dump XML structure is not full', 'PackerStructure');
    return;
  }

  my $userNode = $self-&gt;makeUserNode($userName, $userPtr);
  $adminNode-&gt;getChild( 'users', 1 )-&gt;addChild($userNode) if defined $userNode;
}

sub removeAdminUser {
  my ( $self, $userName ) = @_;

  my $adminNode = $self-&gt;{admin};
  my $usersNode = $adminNode-&gt;getChild( 'users' );

  if ( defined $usersNode ) {
    $usersNode-&gt;removeChildByAttribute( 'user', 'name', $userName );
  }
}

sub addAdminPermission {
  my ( $self, $name, $value ) = @_;

  my $adminNode = $self-&gt;{admin};
  if ( !defined($adminNode) ) {
    Logging::warning('Unable to dump admin permissions, because of dump XML structure is not full', 'PackerStructure');
    return;
  }
  $self-&gt;makePermissionNode( $adminNode-&gt;getChild( 'limits-and-permissions', 1 ), $name, $value );
}

sub addClientUser {
    my ( $self, $ownerId, $userName, $userPtr ) = @_;

    my $clientNode = $self-&gt;getCashedClientNode($ownerId);
    return unless defined $clientNode;

    my $userNode = $self-&gt;makeUserNode($userName, $userPtr);
    $clientNode-&gt;getChild( 'users', 1 )-&gt;addChild($userNode) if defined $userNode;
}

sub removeClientUser {
  my ( $self, $ownerId, $userName ) = @_;

  my $clientNode = $self-&gt;getCashedClientNode($ownerId);
  my $usersNode = $clientNode-&gt;getChild( 'users' );

  if ( defined $usersNode ) {
    $usersNode-&gt;removeChildByAttribute( 'user', 'name', $userName );
  }
}

sub addRootUser {
  my ( $self, $userName, $userPtr ) = @_;

  if (!exists $_rootUsers{$userName}) {
    my $userNode = $self-&gt;makeUserNode($userName, $userPtr);
    $_rootUsers{$userName} = $userNode if defined $userNode;
  }
}

sub removeRootUser {
  my ( $self, $userName ) = @_;
  if ( exists $_rootUsers{$userName} ) {
    delete $_rootUsers{$userName};
  }
}

sub addRootUsers {
    my ( $self ) = @_;

    my $rootNode = $self-&gt;{root};
    if ( !defined($rootNode) ) {
      Logging::warning('Unable to dump root users, because of dump XML structure is not full', 'PackerStructure');
      return;
    }

    if (%_rootUsers) {
      foreach my $userName (keys %_rootUsers) {
        $rootNode-&gt;addChild($_rootUsers{$userName});
      }
    }
}

sub addRoleToRoles {
    my ( $self, $roleNode, $rolesNode ) = @_;

    my @roles  = $rolesNode-&gt;getChildren( 'role' );
    foreach my $role ( @roles ) {
      return if $role-&gt;getAttribute('name') eq $roleNode-&gt;getAttribute('name');
    }
    $rolesNode-&gt;addChild( $roleNode );
}

sub addAdminRole {
    my ( $self, $roleName, $isBuiltIn, $permsPtr, $servicePermissions ) = @_;

    my $adminNode = $self-&gt;{admin};
    if ( !defined($adminNode) ) {
      Logging::warning('Unable to dump admin role, because of dump XML structure is not full', 'PackerStructure');
      return;
    }

    my $roleNode = $self-&gt;makeRoleNode($roleName, $isBuiltIn, $permsPtr, $servicePermissions);
    $self-&gt;addRoleToRoles( $roleNode, $adminNode-&gt;getChild( 'roles', 1 ) );
}

sub removeAdminRole {
  my ( $self, $roleName ) = @_;

  my $adminNode = $self-&gt;{admin};
  my $rolesNode = $adminNode-&gt;getChild( 'roles' );

  if ( defined $rolesNode ) {
    $rolesNode-&gt;removeChildByAttribute( 'role', 'name', $roleName );
  }
}

sub addClientRole {
  my ( $self, $ownerId, $roleName, $isBuiltIn, $permsPtr, $servicePermissions ) = @_;

  my $clientNode = $self-&gt;getCashedClientNode($ownerId);
  return unless defined $clientNode;

  my $roleNode = $self-&gt;makeRoleNode($roleName, $isBuiltIn, $permsPtr, $servicePermissions);
  $self-&gt;addRoleToRoles( $roleNode, $clientNode-&gt;getChild( 'roles', 1 ) );
}

sub removeClientRole {
  my ( $self, $ownerId, $roleName ) = @_;

  my $clientNode = $self-&gt;getCashedClientNode($ownerId);
  my $rolesNode = $clientNode-&gt;getChild( 'roles' );

  if ( defined $rolesNode ) {
    $rolesNode-&gt;removeChildByAttribute( 'role', 'name', $roleName );
  }
}

sub addRootRole {
  my ( $self, $roleName, $isBuiltIn, $permsPtr, $servicePermissions ) = @_;

  if (!exists $_rootRoles{$roleName}) {
      my $roleNode = $self-&gt;makeRoleNode($roleName, $isBuiltIn, $permsPtr, $servicePermissions);
      $_rootRoles{$roleName} = $roleNode if defined $roleNode;
    }
}

sub removeRootRole {
  my ( $self, $roleName ) = @_;
  if ( exists $_rootRoles{$roleName} ) {
    delete $_rootRoles{$roleName};
  }
}

sub addRootRoles {
  my ( $self ) = @_;

  my $rootNode = $self-&gt;{root};
  if ( !defined($rootNode) ) {
    Logging::warning('Unable to dump root roles, because of dump XML structure is not full', 'PackerStructure');
    return;
  }

  if (%_rootRoles) {
    foreach my $roleName (keys %_rootRoles) {
      $self-&gt;addRoleToRoles( $_rootRoles{$roleName}, $rootNode );
    }
  }
}

sub getCashedClientNode {
  my ($self, $clientId) = @_;
  my $root = $self-&gt;{resellersNodes}-&gt;{$clientId};
  unless ( defined($root) ) {
    $root = $self-&gt;{clientNodes}-&gt;{$clientId};
  }
  return $root if defined($root);

  my $caller = (caller(1))[3];
  if (defined $caller) {
    Logging::warning("Error in $caller : empty client parent node for id ($clientId)", 'PackerStructure');
  }
  else {
    Logging::warning('Unable to dump client settings, because of dump XML structure is not full', 'PackerStructure');
  }
  return;
}

my %_requiredLimits = (
  domain =&gt; ['max_subdom', 'max_dom_aliases', 'disk_space', 'max_traffic', 'max_wu', 'max_db',
             'max_box', 'mbox_quota', 'max_maillists', 'max_webapps', 'expiration', 'max_site'],
  client =&gt; ['max_dom', 'max_subdom', 'max_dom_aliases', 'disk_space', 'max_traffic', 'max_wu',
             'max_db', 'max_box', 'mbox_quota', 'max_maillists', 'max_webapps', 'expiration'],
  reseller =&gt; ['max_cl', 'max_dom', 'max_subdom', 'max_dom_aliases', 'disk_space', 'max_traffic', 'max_wu',
               'max_db', 'max_box', 'mbox_quota', 'max_maillists', 'max_webapps', 'expiration']
);

sub fixDefaultLimits {
  my ($self, $type, $id) = @_;
  my $node;
  my $requiredLimits;

  if ( ($type eq 'client') || ($type eq 'reseller') ) {
    $node = $self-&gt;getCashedClientNode($id);
  }
  elsif ($type eq 'domain') {
    $node = $self-&gt;getCashedDomainNode($id);
  }
  return unless defined $node;

  $requiredLimits = $_requiredLimits{$type};

  my %usedLimits;
  XPath::Select $node, 'limits-and-permissions/limit', sub {
    $usedLimits{ shift-&gt;getAttribute( 'name' ) } = 1;
  };

  for my $name ( @{$requiredLimits} ) {
    if ( !exists( $usedLimits{$name} ) ) {
      my $value = ( $name eq 'max_site' ) ? '1' : '-1';
      $self-&gt;insertLimitNode( $node, $name, $value );
    }
  }
}

my %smbUserPinfo = (
  'phone'         =&gt; 'phone',
  'phoneType'     =&gt; 'phone-type',
  'phone2'        =&gt; 'phone2',
  'phone2Type'    =&gt; 'phone2-type',
  'phone3'        =&gt; 'phone3',
  'phone3Type'    =&gt; 'phone3-type',
  'imNumber'      =&gt; 'im',
  'imType'        =&gt; 'im-type',
  'additionalInfo' =&gt;  'comment',
  'email'         =&gt;  'email',
  'companyName'   =&gt;  'company',
  'fax'           =&gt;  'fax',
  'address'       =&gt;  'address',
  'city'          =&gt;  'city',
  'state'         =&gt;  'state',
  'zip'           =&gt;  'zip',
  'country'       =&gt;  'country'
);

sub makeUserNode {
  my ( $self, $userName, $userPtr ) = @_;

  my %user = %{$userPtr};

  my $userNode = XmlNode-&gt;new( 'user' );

  $userNode-&gt;setAttribute( 'name',        $userName );
  if (defined $user{'contactName'}) {
    $userNode-&gt;setAttribute( 'contact',     $user{'contactName'} );
  }else {
    $userNode-&gt;setAttribute( 'contact',     $userName );
  }
  $userNode-&gt;setAttribute( 'guid',        $user{'uuid'}) if defined $user{'uuid'};
  $userNode-&gt;setAttribute( 'email',       $user{'email'} ) if defined $user{'email'};
  $userNode-&gt;setAttribute( 'is-built-in', $user{'isBuiltIn'} ? 'true' : 'false' ) if exists $user{'isBuiltIn'};
  $userNode-&gt;setAttribute( 'cr-date',     $user{'creationDate'} ) if exists $user{'creationDate'};
  $userNode-&gt;setAttribute( 'external-id', $user{'externalId'} ) if defined $user{'externalId'};

  if (defined $user{'subscriptionDomainId'} and $user{'subscriptionDomainId'} != 0) {
    my $subscriptionName = PleskStructure::getDomainNameFromId($user{'subscriptionDomainId'});
    if ($subscriptionName) {
      $userNode-&gt;setAttribute( 'subscription-name', $subscriptionName );
    }else{
      $userNode-&gt;setAttribute( 'subscription-name', 'removed');
    }
  }

  $userNode-&gt;setAttribute( 'is-domain-admin', (defined $user{'isDomainAdmin'} and ( $user{'isDomainAdmin'} eq '1' ) )? 'true' : 'false' );
  $userNode-&gt;setAttribute( 'is-legacy-user', (defined $user{'isLegacyUser'} and ( $user{'isLegacyUser'} eq '1' ) ) ? 'true' : 'false' );
  $userNode-&gt;setAttribute( 'file-sharing-id', $user{'fileSharingId'} ) if defined $user{'fileSharingId'};

  $userNode-&gt;setAttribute( 'external-email', 'true' ) if not defined $user{'mailId'};

  my $propsNode = XmlNode-&gt;new('properties');
  my $passwordNode = CommonPacker::makePasswordNode($userPtr-&gt;{'password'}, (defined $userPtr-&gt;{'passwordType'})? $userPtr-&gt;{'passwordType'} : 'plain', (defined $userPtr-&gt;{'isBase64'} and $userPtr-&gt;{'isBase64'} eq '0') ? undef : 'base64');
  $propsNode-&gt;addChild($passwordNode);

  my $status = $userPtr-&gt;{'isLocked'} ? $Status::ADMIN : $Status::ENABLED;
  $propsNode-&gt;addChild(Status::make($status));

  $userNode-&gt;addChild($propsNode);

  my $lpNode = $userNode-&gt;getChild('limits-and-permissions', 1);
  $lpNode-&gt;addChild(XmlNode-&gt;new('role-ref', 'content' =&gt; $userPtr-&gt;{'SmbRoleName'}));

  foreach my $app (@{$user{'assignedApplications'}}) {
    $lpNode-&gt;addChild(XmlNode-&gt;new('assigned-application', 'content' =&gt; $app));
  }

  my $prefsNode = XmlNode-&gt;new('preferences');

  my @usersPhones;
  foreach my $pinfo (keys %user) {
    next unless defined $smbUserPinfo{$pinfo};
    if ( defined $user{$pinfo} and $user{$pinfo} ne '' ) {
      next if ( $smbUserPinfo{$pinfo} =~ /phone(\d?)-type/);
      if ($smbUserPinfo{$pinfo} =~ /^phone(\d?)$/) {
        push @usersPhones,  $user{$pinfo};
        next;
      }
      $prefsNode-&gt;addChild(XmlNode-&gt;new('pinfo',
                                        'attributes' =&gt; {'name' =&gt; $smbUserPinfo{$pinfo} },
                                        'content' =&gt; $user{$pinfo}
                                        )
                          );
    }
  }
  if (@usersPhones) {
    $prefsNode-&gt;addChild( XmlNode-&gt;new('pinfo',
                       'attributes' =&gt; { 'name' =&gt; 'phone' },
                       'content' =&gt; join(',', @usersPhones)
              )
    );
  }

  $userNode-&gt;addChild($prefsNode);

  return $userNode;
}

sub makeRoleNode {
  my ( $self, $roleName, $isBuiltIn, $permsPtr, $servicePermissions ) = @_;

  my $roleNode = XmlNode-&gt;new( 'role' );
  $roleNode-&gt;setAttribute( 'name', $roleName );
  $roleNode-&gt;setAttribute( 'is-built-in', $isBuiltIn? 'true' : 'false' );

  my $limitsAndPermsNode = XmlNode-&gt;new( 'limits-and-permissions' );
  $roleNode-&gt;addChild($limitsAndPermsNode);

  while ( my ( $name, $value ) = each( %{$permsPtr} ) ) {
    my $permNode = XmlNode-&gt;new( 'permission', 'attributes' =&gt; {
                                                'name'  =&gt; $name,
                                                'value' =&gt; $value? 'true' : 'false' }
                               );
    $limitsAndPermsNode-&gt;addChild( $permNode );
  }

  for my $perm (@$servicePermissions) {
    if ($perm-&gt;{classname} == "Smb_Service_Provider_Aps") {
      my $permNode = XmlNode-&gt;new('service-permission', 'attributes' =&gt; {
        'classname' =&gt; $perm-&gt;{'classname'},
        'description' =&gt; $perm-&gt;{'description'},
        'externalId' =&gt; $perm-&gt;{'externalId'},
        'permissionCode' =&gt; $perm-&gt;{'permissionCode'},
        'class' =&gt; $perm-&gt;{'class'},
        'value' =&gt; 'true',
      });
      $limitsAndPermsNode-&gt;addChild( $permNode );
    }
  }

  return $roleNode;
}

sub makeDomainNode {
    my ( $self, $domainId, $domainName, $domainPtr, $issite, $needFullInfo ) = @_;

    unless ( ref($domainPtr) =~ /HASH/ ) {
      Logging::warning("Unable to backup domain $domainName");
      return;
    }

    my %domain = %{$domainPtr};

    my $nodeName = ($issite? 'site' : 'domain');

    my $root = XmlNode-&gt;new( $nodeName, 'attributes' =&gt; {
        'name' =&gt; $domainName,
        'id'   =&gt; $domainId }
     );

    $root-&gt;getChild( 'preferences', 1 );
    $root-&gt;getChild( 'properties', 1 );
    $root-&gt;getChild( 'limits-and-permissions', 1 ) unless $issite;

    $root-&gt;setAttribute( 'cr-date', $domain{'cr_date'} ) if exists $domain{'cr_date'};
    $root-&gt;setAttribute( 'guid', $domain{'guid'} ) if defined $domain{'guid'};

    $root-&gt;setAttribute( 'external-id', $domain{'external_id'} ) if ( defined $domain{'external_id'} and $domain{'external_id'} ne '');

    $root-&gt;setAttribute( 'vendor-guid', $domain{'vendor-guid'} ) if ( not $issite and defined $domain{'vendor-guid'} );

    $root-&gt;setAttribute( 'owner-guid', $domain{'owner-guid'} ) if ( not $issite and defined $domain{'owner-guid'} );

    $root-&gt;setAttribute( 'owner-name', $domain{'owner-name'} ) if ( not $issite and defined $domain{'owner-name'} );

    $root-&gt;setAttribute( 'parent-domain-name', $domain{'parentDomainName'} ) if ( $issite and defined $domain{'parentDomainName'} );

    $root-&gt;setAttribute( 'vendor-login', $domain{'vendor-login'} ) if ( not $issite and defined $domain{'vendor-login'} );

    if($issite) {
      $self-&gt;{siteNodes}-&gt;{$domainId} = $root;
    }
    else {
      $self-&gt;{domainNodes}-&gt;{$domainId} = $root;
    }

    if ($needFullInfo) {
      return $root;
    } else {
      my $shortInfoNode = XmlNode-&gt;new('domain-info');
      $shortInfoNode-&gt;setAttribute('name', $domainName);
      $shortInfoNode-&gt;setAttribute('guid', $domain{'guid'}) if defined $domain{'guid'};
      unless($issite) {
        $self-&gt;{domainShortNodes}-&gt;{$domainId} = $shortInfoNode;
      }
      return $shortInfoNode;
    }
}

sub getCashedDomainNode {
  my ($self, $domainId) = @_;
  my $root = $self-&gt;{domainNodes}-&gt;{$domainId};
  unless ( defined($root) ) {
    $root = $self-&gt;{siteNodes}-&gt;{$domainId};
  }
  return $root if defined($root);

  my $caller = (caller(1))[3];
  if (defined $caller) {
    Logging::warning("Error in $caller : empty domain parent node for id ($domainId)", 'PackerStructure');
  }
  else {
    Logging::warning('Error: empty domain parent node', 'PackerStructure');
  }
  return;
}

sub finishDomain {
  my ( $self, $domainId) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  #TODO: uncomment
  #$root-&gt;ReleaseCode();
}

sub setDomainWwwStatus {
  my ( $self, $domainId, $status ) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  $root-&gt;setAttribute( 'www', $status );
}

sub setDomainIP {
  my ( $self, $domainId, $ip, $iptype ) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  $root-&gt;getChild( 'properties', 1 )-&gt;addChild( $self-&gt;makeIpNode( $ip, $iptype ), 1 );
}

sub setDomainStatus {
  my ( $self, $domainId, $status ) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  $root-&gt;getChild( 'properties', 1 )-&gt;addChild( Status::make($status) );
}

sub setWebspaceStatus {
  my ( $self, $domainId, $status, $siteStatus ) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  if (not defined $siteStatus) {
    $root-&gt;getChild( 'properties', 1 )-&gt;addChild( Status::make($status, 'webspace-status') );
    $root-&gt;getChild( 'properties', 1 )-&gt;addChild( Status::make($status) );
  } else {
    $root-&gt;getChild( 'properties', 1 )-&gt;addChild( Status::make($status, 'webspace-status') );
    $root-&gt;getChild( 'properties', 1 )-&gt;addChild( Status::make($siteStatus) );
  }
}

sub getDomainARecordIp {
  my ( $self, $domainId ) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my $name = PleskStructure::getDomainNameFromId($domainId);
  my $aRecordIp;
  XPath::Select $root, 'properties/dns-zone/dnsrec', sub {
    my $rec = shift;
    if (($rec-&gt;getAttribute('type') eq 'A') or ($rec-&gt;getAttribute('type') eq 'AAAA') and ($rec-&gt;getAttribute('src') eq "$name.") ) {
      $aRecordIp = $rec-&gt;getAttribute('dst');
    }
  };
  return $aRecordIp;
}

sub addDomainDatabase {
  my ( $self, $dbId, $dbServerId, $domainId, $dbName, $dbType, $optionalPtr, $dbServerPtr, $dbUsersPtr, $contentDescriptionPtr, $skipContent ) = @_;

  $self-&gt;regDatabaseObjectBackupPath( $self-&gt;getDomainsBackupPath( $domainId ), $dbId, $dbName, $dbServerId );
  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my $node = $self-&gt;makeDatabaseNode( $dbId, $dbName, $dbType, 'domain', $domainId, $optionalPtr,
                                      $dbServerPtr, $dbUsersPtr, $contentDescriptionPtr, $skipContent );
  my $parentGuid = $root-&gt;getAttribute('guid');
  $node-&gt;setAttribute( 'guid', $self-&gt;getDatabaseGuid( $parentGuid, $dbId ) ) if $parentGuid;
  $node-&gt;setAttribute( 'owner-guid', $parentGuid ) if $parentGuid;

  $root-&gt;getChild( 'databases', 1 )-&gt;addChild($node);
}

sub setDomainDefault {
  my ( $self, $domainId ) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  $root-&gt;getChild( 'preferences', 1 )-&gt;addChild( XmlNode-&gt;new('default-domain') );
}

sub addDomainLimit {
  my ( $self, $domainId, $name, $value ) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  $self-&gt;insertLimitNode( $root, $name, $value );
}

sub setDomainMailService {
  my ( $self, $domainId, $status, $ips ) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my $mailServiceStatus = Status::make($status);

  my $rootMail = XmlNode-&gt;new('mailsystem');
  my $properties = $rootMail-&gt;getChild( 'properties', 1 );
  $properties-&gt;addChild($mailServiceStatus);

  foreach my $ip (keys %{$ips}) {
    my $ipNode = $self-&gt;makeIpNode($ip, $ips-&gt;{$ip});
    $properties-&gt;addChild($ipNode);
  }

  $root-&gt;addChild($rootMail);
}

sub addDomainCustomButton {
  my ( $self, $domainId, $id, $optionsPtr, $customButtonsDir, $icon ) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my $node = $self-&gt;makeCustomButtonNode( 'domains', $domainId, $id, $optionsPtr, $customButtonsDir, $icon );

  $root-&gt;getChild( 'preferences', 1 )-&gt;addChild( $node);
}

sub addToPreferences {
  my ( $self, $objectType, $objectId, $node ) = @_;

  my $parent;
  if ($objectType eq 'domain') {
    $parent = $self-&gt;getCashedDomainNode($objectId);
  }
  elsif($objectType eq 'client') {
    $parent = $self-&gt;{clientNodes}-&gt;{$objectId};
  }
  if ( !defined($parent) ) {
    Logging::warning('Error: addToPreferences: empty parent node', 'PackerStructure');
    return;
  }

  $parent-&gt;getChild( 'preferences', 1 )-&gt;addChild( $node);
}

sub setDomainCatchMail {
  my ( $self, $domainId, $catchAllAddr ) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my $mailService = $root-&gt;getChild('mailsystem');
  unless (defined $mailService ) {
    Logging::warning("Error: setDomainCatchMail: there are no node 'mailsystem'", 'PackerStructure');
    return;
  }

  $mailService-&gt;getChild( 'preferences', 1 )-&gt;addChild(XmlNode-&gt;new( 'catch-all', 'content' =&gt; $catchAllAddr ) );
}

sub setDomainKeysDomainSupport {
  my ( $self, $domainId, $domainName, $state, $privateKeyPath, $publickKey ) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my $mailService = $root-&gt;getChild('mailsystem');
  unless ( defined $mailService ) {
    Logging::warning("Error: setDomainKeysDomainSupport: there are no node 'mailsystem'", 'PackerStructure');
    return;
  }

  my $domainKeysNode = XmlNode-&gt;new( 'domain-keys',
    'attributes' =&gt; { 'state' =&gt; $state } );

  if ($state) {
    my $privateKey = $self-&gt;{content_transport}-&gt;addDomainContent( 'key', $domainId,
      "privatekey",
      'directory' =&gt; $privateKeyPath,
      'include'   =&gt; ['default']
    );

    $domainKeysNode-&gt;getChild( 'content', 1, 1 )-&gt;addChild( $privateKey ) if $privateKey;

    $domainKeysNode-&gt;setAttribute( 'public-key', $publickKey ) if ( defined($publickKey) &amp;&amp; $publickKey );
  }

  $mailService-&gt;getChild( 'preferences', 1 )-&gt;addChild($domainKeysNode);
}

sub setDomainWebMail{
  my ( $self, $domainId, $webmail, $cert ) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my $mailService = $root-&gt;getChild('mailsystem');
  if ( not $mailService ) {
    Logging::warning("Unable to dump domain webmail preferences, because of dump XML structure is not full", 'PackerStructure');
    return;
  }

  my $node = XmlNode-&gt;new( 'web-mail' );
  $node-&gt;setText( $webmail );
  $node-&gt;setAttribute('certificate', $cert) if defined $cert;
  $mailService-&gt;getChild( 'preferences', 1 )-&gt;addChild( $node );
}

sub setDomainGLSupport {
  my ( $self, $domainId, $state ) = @_;
  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my $mailsystem = $root-&gt;getChild('mailsystem');
  my $node = XmlNode-&gt;new( 'grey-listing' );
  $node-&gt;setText($state);
  $mailsystem-&gt;getChild('preferences', 1)-&gt;addChild($node);
}

sub setDomainDnsZone {
  my ( $self, $domainId, $paramsPtr, $recordsPtr ) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  $self-&gt;makeDnsZone($root-&gt;getChild( 'properties', 1 ), $paramsPtr, $recordsPtr);
}

sub removeDomainDnsZone {
  my ( $self, $domainId ) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my $propertiesNode = $root-&gt;getChild( 'properties');
  if ( $propertiesNode ) {
    $propertiesNode-&gt;removeChildren('dns-zone');
  }
}

sub setDomainDnsOld {
  my ( $self, $domainId, $enabled, $type, $masterIp, $recordsPtr ) = @_;

  my @records = @{$recordsPtr};

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my $properties = $root-&gt;getChild( 'properties', 1 );
  if ( !defined($properties) ) {
    Logging::warning("Error: setDomainDnsOld: empty 'properties' node", 'PackerStructure');
    return;
  }

  my $dnsNode = XmlNode-&gt;new('dns-zone');

  $dnsNode-&gt;setAttribute(
    'type',
    ( !$type || ( $type eq 'master' ) ) ? 'master' : 'slave'
  );

	$dnsNode-&gt;addChild(Status::make( $enabled eq 'true' ? 0 : 16 ));

  for my $hash (@records) {
    my $dnsrec = $self-&gt;makeDnsRecord($hash);
    if ($dnsrec) {
      $dnsNode-&gt;addChild($dnsrec);
    }
    $hash = undef;
  }

  if ( defined($masterIp) ) {
    $dnsNode-&gt;addChild( makeOldMasterRec($masterIp) );
  }

  $properties-&gt;addChild($dnsNode);
}

sub addDomainAlias {
  my ( $self, $domainId, $aliasPtr, $dnsParamsPtr, $dnsRecordsPtr) = @_;

  my %alias = %{$aliasPtr};

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my $dnsSync = defined $alias{'dns'} ? $alias{'dns'} : 'false';
  
  my $aliasNode = XmlNode-&gt;new(
    'domain-alias',
    'attributes' =&gt; {
      'name' =&gt; $alias{'displayName'},
      'mail' =&gt; $alias{'mail'},
      'web'  =&gt; $alias{'web'},
      'dns'  =&gt; $dnsSync
    },
    'children' =&gt; [ Status::make( $alias{'status'} ) ]
  );

  $aliasNode-&gt;setAttribute( 'tomcat', $alias{'tomcat'} )
    if defined $alias{'tomcat'};

  $aliasNode-&gt;setAttribute('seo-redirect', defined $alias{'seoRedirect'} ? $alias{'seoRedirect'} : 'false');

  $aliasNode-&gt;setAttribute('external-id', $alias{'external_id'}) if defined $alias{'external_id'} and $alias{'external_id'} ne '';

  # DNS zone

  if ( $alias{'dns_zone_id'} != 0 ) {
    $self-&gt;makeDnsZone( $aliasNode, $dnsParamsPtr, $dnsRecordsPtr, $dnsSync );
  }

  $root-&gt;getChild( 'preferences', 1 )-&gt;addChild($aliasNode);
}

sub setDomainMailLists {
  my ( $self, $domainId, $status, $ips) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my $mlNode = XmlNode-&gt;new('maillists');

  my $propertiesNode = $mlNode-&gt;getChild( 'properties', 1 );
  $propertiesNode-&gt;addChild( Status::make( $status ) );
  foreach my $ip (keys %{$ips}) {
    my $ipNode = $self-&gt;makeIpNode($ip, $ips-&gt;{$ip});
    $propertiesNode-&gt;addChild($ipNode);
  }

  $root-&gt;addChild($mlNode);
}

sub addDomainMailList {
  my ($self, $domainId, $name, $passwd, $state, $ownersPtr, $membersPtr) = @_;

  my @owners = @{$ownersPtr};
  my %members = %{$membersPtr};

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my @mailListServs = $root-&gt;getChildren('maillists');
  if ( scalar(@mailListServs) &lt; 1 ) {
    Logging::warning('Unable to dump domain maillist, because of dump XML structure is not full', 'PackerStructure');
    return;
  }
  my $mailListService = $mailListServs[0];

  my $node = XmlNode-&gt;new(
    'maillist',
    'attributes' =&gt; { 'name', $name },
    'children'   =&gt; [ Status::make($state) ]
  );

  for my $listOwner (@owners) {
    $node-&gt;addChild( XmlNode-&gt;new( 'owner', 'content' =&gt; $listOwner ) );
  }

  $node-&gt;addChild( CommonPacker::makePasswordNode( $passwd, 'encrypted') );

  for my $memberEmail ( keys %members ) {
    my $member = XmlNode-&gt;new( 'recipient', 'content' =&gt; $memberEmail );
    if ( $members{$memberEmail} ne "" ) {
      $member-&gt;setAttribute( 'fullname', $members{$memberEmail} );
    }
    $node-&gt;addChild($member);
  }

  $mailListService-&gt;addChild($node);
}

sub setDomainTraffic {
  my ( $self, $domainId, $trafficValue) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  $root-&gt;addChild( XmlNode-&gt;new( 'traffic', 'content' =&gt; $trafficValue ) );
}

sub addDomainCertificate {
  my ( $self, $domainId, $name, $cert, $csr, $ca_cert, $pvt_key, $default) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my $certNode = XmlNode-&gt;new('certificate');

  addUrlDecodedTextNode( $certNode, 'certificate-data', $cert ) if defined($cert);
  addUrlDecodedTextNode( $certNode, 'signing-request',  $csr ) if defined($csr);
  addUrlDecodedTextNode( $certNode, 'ca-certificate',   $ca_cert ) if defined($ca_cert);
  addUrlDecodedTextNode( $certNode, 'private-key', $pvt_key ) if defined($pvt_key);
  $certNode-&gt;setAttribute( 'name', $name );
  $certNode-&gt;setAttribute( 'default', 'true' ) if ( defined $default &amp;&amp; $default == 1 );

  $root-&gt;getChild('certificates', 1 )-&gt;addChild($certNode);
}

sub setDomainTomcat {
  my ( $self, $domainId, $status, $ips) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my $tomcatNode = XmlNode-&gt;new('tomcat');

  my $propertiesNode = $tomcatNode-&gt;getChild( 'properties', 1 );
  $propertiesNode-&gt;addChild( Status::make( $status ) );
  foreach my $ip (keys %{$ips}) {
    my $ipNode = $self-&gt;makeIpNode($ip, $ips-&gt;{$ip});
    $propertiesNode-&gt;addChild($ipNode);
  }
  $root-&gt;addChild($tomcatNode);
}

sub addDomainTomcatWebApp {
  my ( $self, $domainId, $domainName, $name, $status, $path) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my @tomcatServs = $root-&gt;getChildren('tomcat');
  if ( scalar(@tomcatServs) &lt; 1 ) {
    Logging::warning('Unable to dump domain Tomcat web-applications, because of dump XML structure is not full', 'PackerStructure');
    return;
  }
  my $tomcatService = $tomcatServs[0];

  my $item = XmlNode-&gt;new(
    'webapp',
    'attributes' =&gt; { 'name' =&gt; $name },
    'children'   =&gt; [ Status::make($status) ]
  );

  my $warFile = "$name.war";

  my $cid = $self-&gt;{content_transport}-&gt;addDomainContent( 'web-app', $domainId,
    "$name.webapp",
    "directory" =&gt; $path,
    "include"   =&gt; [$warFile]
  );
  $item-&gt;getChild( 'content', 1, 1 )-&gt;addChild( $cid ) if $cid;

  $tomcatService-&gt;addChild($item);
}

sub addDomainPersonalPermission {
  my ( $self, $domainId, $name, $value ) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  if ( !defined($root) ) {
    Logging::warning('Unable to dump domain personal permissions, because of dump XML structure is not full', 'PackerStructure');
    return;
  }

  $self-&gt;makePermissionNode( $root-&gt;getChild( 'limits-and-permissions', 1 ), $name, $value );
}

sub setDomainPhostingEmpty {
  my ( $self, $domainId, $sysuserPtr, $ips ) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my $phostingNode = XmlNode-&gt;new('phosting');

  my $preferencesNode = XmlNode-&gt;new('preferences');
  $phostingNode-&gt;addChild( $preferencesNode );

  if (defined $sysuserPtr) {
    $preferencesNode-&gt;addChild($self-&gt;makeSysUser($sysuserPtr));
  }
  
  my $propertiesNode = $phostingNode-&gt;getChild( 'properties', 1 );
  foreach my $ip (keys %{$ips}) {
    my $ipNode = $self-&gt;makeIpNode($ip, $ips-&gt;{$ip});
    $propertiesNode-&gt;addChild($ipNode);
  }

  $root-&gt;addChild($phostingNode);

  $self-&gt;regPhostingObjectBackupPath( $self-&gt;getDomainsBackupPath( $domainId ), $domainId );
  $self-&gt;{phostingNodes}-&gt;{$domainId} = $phostingNode;
}

sub setDomainPhosting {
  my ( $self, $domainId, $paramsPtr, $sysuserPtr, $scriptingPtr, $ips, $phpSettingsPtr ) = @_;

  my %params = %{$paramsPtr};
  my %scripting = %{$scriptingPtr};

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my $phostingNode = XmlNode-&gt;new('phosting');

  my $parentGuid = $root-&gt;getAttribute('guid');
  if ( $parentGuid ) {
    $phostingNode-&gt;setAttribute( 'guid', $self-&gt;getPhostingGuid( $parentGuid , $domainId ) );
    $phostingNode-&gt;setAttribute( 'owner-guid', $parentGuid );
  }

  ## %params ##
  my %hostingAttribute = (
    'https'   =&gt; 'ssl',
    'webstat' =&gt; 'webstat',
  );
  $phostingNode-&gt;setAttribute( 'shared-content', $params{'shared-content'} ) if defined($params{'shared-content'});
  while ( my ( $xmlName, $fieldName ) = each(%hostingAttribute) ) {
    # MySQL allows 'true', 'false' and '' in enums
    if ( defined( $params{$fieldName} )
      and $params{$fieldName} eq "true" )
    {
      $phostingNode-&gt;setAttribute( $xmlName, 'true' );
    }
  }

  if ( defined( $params{'webstat'} ) and $params{'webstat'} ) {
    $phostingNode-&gt;setAttribute( 'webstat', $params{'webstat'} );
  }

  if ( defined( $params{'https'} ) and $params{'https'} ) {
    $phostingNode-&gt;setAttribute( 'https', $params{'https'} );
  }

  if ( defined( $params{'sslRedirect'} ) and $params{'sslRedirect'} ) {
    $phostingNode-&gt;setAttribute( 'sslRedirect', $params{'sslRedirect'} );
  }

  if ( defined($params{'errdocs'} ) ) {
    $phostingNode-&gt;setAttribute( 'errdocs', 'true' );
  }

  if ( defined( $params{'www-root'} ) ) {
    $phostingNode-&gt;setAttribute( 'www-root', $params{'www-root'} );
  }

  if ( defined( $params{'cgi_bin_mode'} ) ) {
    $phostingNode-&gt;setAttribute( 'cgi_bin_mode', $params{'cgi_bin_mode'} );
  }

  if ( defined( $params{'sitebuilder-site-id'} ) ) {
    $phostingNode-&gt;setAttribute( 'sitebuilder-site-id', $params{'sitebuilder-site-id'} );
  }

  if ( defined( $params{'sitebuilder-site-published'} ) ) {
    $phostingNode-&gt;setAttribute( 'sitebuilder-site-published', $params{'sitebuilder-site-published'} );
  }

  if ( defined( $params{'wu_script'} ) ) {
    $phostingNode-&gt;setAttribute( 'wu_script', $params{'wu_script'} );
  }

  if ( defined( $params{'certificate_ref'} ) ) {
    $phostingNode-&gt;setAttribute( 'certificate', $params{'certificate_ref'} );
  }

  if ( defined( $params{'original-conf-directory'} ) ) {
    $phostingNode-&gt;setAttribute( 'original-conf-directory', $params{'original-conf-directory'} );
  }

  ## %sysuser ##
  my $prefs = $phostingNode-&gt;getChild( 'preferences', 1 );
  if (defined $sysuserPtr) {
    my $sysUserNode = $self-&gt;makeSysUser($sysuserPtr);
    $prefs-&gt;addChild($sysUserNode);
  }

  ## properties ##
  my $propertiesNode = $phostingNode-&gt;getChild( 'properties', 1);
  foreach my $ip (keys %{$ips}) {
    my $ipNode = $self-&gt;makeIpNode($ip, $ips-&gt;{$ip});
    $propertiesNode-&gt;addChild($ipNode);
  }

  ## %scripting ##
  my $scripringItem = XmlNode-&gt;new('scripting');
  while ( my ( $scriptXmlName, $value ) = each(%scripting) ) {
    $scripringItem-&gt;setAttribute( $scriptXmlName, $value ) if defined $value;
  }
  $phostingNode-&gt;getChild( 'limits-and-permissions', 1 )-&gt;addChild($scripringItem);

  if (defined $phpSettingsPtr and (scalar keys %{$phpSettingsPtr} != 0)) {
    $phostingNode-&gt;addChild($self-&gt;makePhpSettingsNode($phpSettingsPtr));
  }

  $root-&gt;addChild($phostingNode);

  $self-&gt;regPhostingObjectBackupPath( $self-&gt;getDomainsBackupPath( $domainId ), $domainId );
  $self-&gt;{phostingNodes}-&gt;{$domainId} = $phostingNode;

}

sub setDomainUserDataContent {
  my ( $self, $domainId, $domainName, $path, $optPtr) = @_;

  if (!$self-&gt;getContentTransport()-&gt;directoryExists("$path")) {
    Logging::debug("Domain $domainName. Skip backup of non-existent directory $path");
    return;
  }

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;
  
  my $phostings = $root-&gt;getChild('phosting');
  
  my ($fhApache, $tmpApache) = File::Temp::tempfile( AgentConfig::getBackupTmpDir() . "/pmm-dudc-incApacheFiles-XXXXXX", UNLINK =&gt; 1 );
  my ($fhUser, $tmpUserData) = File::Temp::tempfile( AgentConfig::getBackupTmpDir() . "/pmm-dudc-incUserData-XXXXXX", UNLINK =&gt; 1 );
  
  chown getpwnam("root"), getgrnam("root"), $tmpApache, $tmpUserData;
  chmod 0600, $tmpApache, $tmpUserData;
  
  my %excludes = map { $_ =&gt; 1 } @{$optPtr-&gt;{'exclude'}};
  Logging::debug("List files in " . $path);
  $self-&gt;_listApacheAndUserFilesInFolder($path, $fhUser, $fhApache, \%excludes);

  close $fhUser;
  close $fhApache;

  my $userDataSize = $self-&gt;_setDomainContentIncrementally($domainId, $path, $optPtr, $tmpUserData, $phostings, 'user-data', $optPtr-&gt;{'sysuser'});
  if ($userDataSize != undef) {
    my $apacheSize = $self-&gt;_setDomainContentIncrementally($domainId, $path, $optPtr, $tmpApache, $phostings, 'apache-files', $self-&gt;{apache_user}{'user'});
    if ($apacheSize != undef) {
      $self-&gt;{stat}{vhostDumpsCount}++;
      $self-&gt;{stat}{vhostSizeDumped} += $userDataSize + $apacheSize;
      return;
    }
  }

  my @apacheFiles;
  my $cmd = "find $path \\( \\( -type d -user $self-&gt;{apache_user}{user} -group $self-&gt;{apache_user}{group} ! -perm -o+rw -prune \\) -o \\( ! -type d -user $self-&gt;{apache_user}{user} -group $self-&gt;{apache_user}{group} ! -perm -o+rw \\) \\) -printf \"%P\n\"";
  my $findCmd = `$cmd`;
  if ($? eq '0') {
    @apacheFiles = split "\n", $findCmd;
  }

  my @exclude = (@apacheFiles) ? (@apacheFiles, @{$optPtr-&gt;{'exclude'}}) : @{$optPtr-&gt;{'exclude'}};
  my $cidUserData = $self-&gt;{content_transport}-&gt;addDomainContent( 'user-data', $domainId,
    'user-data',
    'directory' =&gt; $path,
    'sysuser' =&gt; $optPtr-&gt;{'sysuser'},
    'exclude' =&gt; \@exclude
  );
  $phostings-&gt;getChild( 'content', 1, 1 )-&gt;addChild( $cidUserData ) if $cidUserData;
  @{$self-&gt;{domainVhost}-&gt;{$domainId}} = ( 'user-data', $cidUserData, $path )  if $cidUserData;

  my $cidApache;
  if (@apacheFiles) {
    $cidApache = $self-&gt;{content_transport}-&gt;addDomainContent( 'apache-files', $domainId,
      'apache-files',
      'directory' =&gt; $path,
      'sysuser' =&gt; $self-&gt;{apache_user}{'user'},
      'include' =&gt; \@apacheFiles
    );
    $phostings-&gt;getChild( 'content', 1, 1 )-&gt;addChild( $cidApache ) if $cidApache;
    @{$self-&gt;{domainVhost}-&gt;{$domainId}} = ( 'apache-files', $cidApache, $path )  if $cidApache;
  }
  
  $self-&gt;{stat}{vhostDumpsCount}++;
  $self-&gt;{stat}{vhostSizeDumped} +=  $self-&gt;_getContentSizeFromCidNode($cidUserData) + $self-&gt;_getContentSizeFromCidNode($cidApache);
}

sub _setDomainContentIncrementally {
  my ($self, $domainId, $srcDirPath, $optPtr, $listingFile, $contentOwner, $cidType, $sysuser, $refferedContentType) = @_;

  $refferedContentType = 'domainVhost' unless defined $refferedContentType;
  my $cidSize = undef;
  
  my $changesFile = HelpFuncs::mktemp(AgentConfig::getBackupTmpDir() . "/pmm-dci-chn-XXXXXXXX");
  my $indexFile = HelpFuncs::mktemp(AgentConfig::getBackupTmpDir() . "/pmm-dci-idx-XXXXXXXX");
  my $dependenciesFile = HelpFuncs::mktemp(AgentConfig::getBackupTmpDir() . "/pmm-dci-dep-XXXXXXXX");

  my $oldMask = umask(0077);
  for my $outFile ( ($changesFile, $indexFile, $dependenciesFile) ) {
    open(my $outFileHandle, '&gt;', $outFile);
    close($outFileHandle);
  }
  umask($oldMask);
  
  my $cmd = [
    AgentConfig::pmmRasBin(), '--get-diff',
    '--listing-file', $listingFile,
    '--backup-file', $self-&gt;{storage}-&gt;{output_dir}."/".$self-&gt;getDomainsBackupPath($domainId, $cidType).".tgz",
    '--changes-file', $changesFile,
    '--index-file', $indexFile,
    '--dependencies-file', $dependenciesFile
  ];
  
  my $cidPostfix = '';
  if ($cidType eq 'domainmail') {
    push (@{$cmd}, '--id');
    push (@{$cmd}, $domainId);
    $cidPostfix = '_' . $domainId;
  }
  
  if ($self-&gt;{lastIndexPath}) {
    push (@{$cmd}, '--last-index-path');
    push (@{$cmd}, $self-&gt;{lastIndexPath});
  }

  if ($self-&gt;{lastIncrementFile}) {
    push (@{$cmd}, '--last-increment-file');
    push (@{$cmd}, $self-&gt;{lastIncrementFile});
  }

  if ($self-&gt;{excludePatternsFile}) {
    push (@{$cmd}, '--exclude-patterns-file');
    push (@{$cmd}, $self-&gt;{excludePatternsFile});
  }

  if (defined($self-&gt;{storage}-&gt;{ftpsettings})) {
    push (@{$cmd}, '--use-ftp-passive-mode') if $self-&gt;{storage}-&gt;{passive_mode};
    $ENV{'DUMP_STORAGE_PASSWD'} = $self-&gt;{storage}-&gt;{ftpsettings}-&gt;{password};
  }

  if (Logging::getVerbosity() &gt;= Logging::LOG_LEVEL_DEBUG) {
    push (@{$cmd}, '--debug');
  }

  if (Logging::getVerbosity() &gt;= Logging::LOG_LEVEL_TRACE) {
    push (@{$cmd}, '--verbose');
  }

  Logging::debug("Execute: ".join(' ', @{$cmd}));

  my($err);
  run $cmd, '&gt;&amp;', \$err;

  if ($?) {
    Logging::debug("Unable to calculate file diff, full dump will be performed instead. Error (".$?.") ".$err, "IncrementalBackup");
  } else {
    my $dumpXmlRelativePath = $self-&gt;getDomainsBackupPath($domainId, 'info', 0);
    my $posNameBegin = rindex( $dumpXmlRelativePath, '/' ) + 1;
    my $dumpName = substr($dumpXmlRelativePath, $posNameBegin);
    my $dumpDirPath = ($posNameBegin &gt; 0) ? substr($dumpXmlRelativePath, 0, $posNameBegin - 1) : "";
    my $indexDirPath = $dumpDirPath;
    if (!$self-&gt;{domainNodes}-&gt;{$domainId}) {
      my $posSitesBegin = rindex($indexDirPath, '/sites/');
      if ($posSitesBegin &gt; 0) {
        $indexDirPath = substr($indexDirPath, 0, $posSitesBegin);
      }
    }

    my $cid_content = $self-&gt;{content_transport}-&gt;addDomainContent( $cidType, $domainId,
      $cidType,
      'directory' =&gt; $srcDirPath,
      'sysuser' =&gt; $sysuser,
      'includes-file' =&gt; $changesFile,
      'exclude' =&gt; \@{$optPtr-&gt;{'exclude'}},
      'no_recursion' =&gt; 1,
      'indexed' =&gt; 1
    );
    if ($cid_content) {
      $self-&gt;{storage}-&gt;moveFileToDiscovered($indexFile, "cid_".$cidType.$cidPostfix, $indexDirPath, $dumpName);
      $contentOwner-&gt;getChild('content', 1, 1)-&gt;addChild($cid_content);
      @{$self-&gt;{$refferedContentType}-&gt;{$domainId}} = ($cidType, $cid_content, $srcDirPath);
      $cidSize = $self-&gt;_getContentSizeFromCidNode($cid_content);
    }

    $self-&gt;_keepRelatedDumps($dumpDirPath, $dependenciesFile);
  }

  unlink($changesFile) if -e $changesFile;
  unlink($indexFile) if -e $indexFile;
  unlink($dependenciesFile) if -e $dependenciesFile;

  return $cidSize;
}

sub _getContentSizeFromCidNode {
  my ($self, $cidNode) = @_;
  
  my $size = 0;
  if ($cidNode) {
    foreach my $contentFileNode ( $cidNode-&gt;getChildren('content-file') ) {
      if ($contentFileNode) {
        $size += $contentFileNode-&gt;getAttribute('size');
      }
    }
  }
  
  return $size;
}

sub _keepRelatedDumps {
  my ($self, $pathToDumpFolder, $relatedDumpsFile) = @_;

  my @relatedDumps = HelpFuncs::loadArrayFromFile($relatedDumpsFile);
  return unless (@relatedDumps);
  
  @relatedDumps = sort(@relatedDumps);  
  $self-&gt;_keepRelatedDumpsTo($pathToDumpFolder, \@relatedDumps);
}

sub _keepRelatedDumpsTo {
  my ($self, $pathToDumpFolder, $relatedDumps) = @_;

  if (exists $self-&gt;{relatedDumps}-&gt;{$pathToDumpFolder}) {
    my @diff = HelpFuncs::arrayDifference($relatedDumps, $self-&gt;{relatedDumps}-&gt;{$pathToDumpFolder});
    my @merged = (@{$self-&gt;{relatedDumps}-&gt;{$pathToDumpFolder}}, @diff);
    @{$self-&gt;{relatedDumps}-&gt;{$pathToDumpFolder}} = sort(@merged);
  } else {
    @{$self-&gt;{relatedDumps}-&gt;{$pathToDumpFolder}} = @{$relatedDumps};
  }

  return if ($pathToDumpFolder eq '');

  my $pathToParentDumpFolder = dirname(dirname($pathToDumpFolder));
  $pathToParentDumpFolder = "" if ($pathToParentDumpFolder eq '.');

  $self-&gt;_keepRelatedDumpsTo($pathToParentDumpFolder, $relatedDumps);
}

sub _listApacheAndUserFilesInFolder {
  my ($self, $srcDirPath, $outUserFiles, $outApacheFiles, $excludes, $isApacheBranch, $szPathTrim, $usersCache, $groupsCache, $orderNumber) = @_;

  return if !opendir(my $dh, $srcDirPath);
  
  $szPathTrim = length($srcDirPath) + 1 if (not defined $szPathTrim or $szPathTrim == 0);
  $$orderNumber = 0 if not defined($orderNumber);

  my @entriesInfo;
  while (my $entry = readdir($dh)) {
    next if ($entry eq "." || $entry eq "..");
    my $entryFullPath = $srcDirPath."/".$entry;
    my $entryRelPath = substr $entryFullPath, $szPathTrim;

    next if (exists($excludes-&gt;{$entryRelPath}));

    my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $mtime, $ctime, $blksize, $blocks) = lstat($entryFullPath) or next;
    push @entriesInfo, join("\t", HelpFuncs::encodePath($entry), ++$$orderNumber, $mode, $uid, $gid, $size, $mtime, $ctime);
  }
  closedir($dh);

  @entriesInfo = sort(@entriesInfo);

  foreach my $entryInfo (@entriesInfo) {
    my ($entry, $entryOrderNumber, $mode, $uid, $gid, $size, $mtime, $ctime) = split("\t", $entryInfo);
    my $entryFullPath = $srcDirPath . "/" . HelpFuncs::decodePath($entry);
    my $entryRelPath = substr $entryFullPath, $szPathTrim;
    
    my $addToApacheListing = $outApacheFiles &amp;&amp; ($isApacheBranch || ($uid == $self-&gt;{apache_user}{uid} &amp;&amp; $gid == $self-&gt;{apache_user}{gid} &amp;&amp; !($mode &amp; Fcntl::S_IROTH &amp;&amp; $mode &amp; Fcntl::S_IWOTH)));
    my $ftype = (Fcntl::S_ISDIR($mode) &amp;&amp; !Fcntl::S_ISLNK($mode)) ? 'd' : 'f';
    my $fsize = ($ftype eq 'd') ? "0" : "$size";
    $mode = sprintf '%04o', $mode &amp; 07777;
    $mtime = HelpFuncs::Max($mtime, $ctime);

    $usersCache-&gt;{$uid} = getpwuid($uid) if (not exists $usersCache-&gt;{$uid});
    $groupsCache-&gt;{$gid} = getgrgid($gid) if (not exists $groupsCache-&gt;{$gid});

    my $outFile = ($addToApacheListing) ? $outApacheFiles : $outUserFiles;
    print $outFile join("\t", HelpFuncs::encodePath($entryRelPath), $ftype, $fsize, $mtime, $entryOrderNumber, $usersCache-&gt;{$uid}, $groupsCache-&gt;{$gid}, $mode) . "\n";

    if ($ftype eq 'd') {
      $self-&gt;_listApacheAndUserFilesInFolder($entryFullPath, $outUserFiles, $outApacheFiles, $excludes, $addToApacheListing, $szPathTrim, $usersCache, $groupsCache, $orderNumber);
    }
  }
}

sub setDomainPhostingFullContent {
  my ( $self, $domainId, $domainName, $path, $optPtr) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my $phostings = $root-&gt;getChild('phosting');
  my $cid_content = $self-&gt;{content_transport}-&gt;addDomainContent( 'vhost', $domainId,
    'vhost',
    'directory' =&gt; $path,
    'sysuser' =&gt; $optPtr-&gt;{'sysuser'},
    'exclude' =&gt; $optPtr-&gt;{'exclude'},
  );
  $phostings-&gt;getChild( 'content', 1, 1 )-&gt;addChild( $cid_content ) if $cid_content;
  @{$self-&gt;{domainVhost}-&gt;{$domainId}} = ( 'vhost', $cid_content, $path )  if $cid_content;
}

sub setDomainMailNamesContent{
  my ( $self, $domainId, $domainAsciiName, $path, $sysuser ) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my %options;
  $options{'directory'} = $path;
  $options{'sysuser'} = $sysuser;

  my ($fhApache, $tmpApache) = File::Temp::tempfile( AgentConfig::getBackupTmpDir() . "/pmm-dmnc-incApacheFiles-XXXXXX", UNLINK =&gt; 1 );
  my ($fhUser, $tmpUserData) = File::Temp::tempfile( AgentConfig::getBackupTmpDir() . "/pmm-dmnc-incUserData-XXXXXX", UNLINK =&gt; 1 );

  chown getpwnam("root"), getgrnam("root"), $tmpApache, $tmpUserData;
  chmod 0600, $tmpApache, $tmpUserData;

  my $optPtr = \%options;
  my %excludes = map { $_ =&gt; 1 } @{$optPtr-&gt;{'exclude'}};
  Logging::debug("List files in " . $path);
  $self-&gt;_listApacheAndUserFilesInFolder($path, $fhUser, $fhApache, \%excludes);

  close $fhUser;
  close $fhApache;

  my $mailsystem = $root-&gt;getChild('mailsystem');

  my $mailContentSize = $self-&gt;_setDomainContentIncrementally(
    $domainId, $path, $optPtr, $tmpUserData, $mailsystem, 'domainmail', $sysuser, 'domainMailContent');

  $self-&gt;{stat}{mailSizeDumped} += $mailContentSize;
  $self-&gt;{stat}{mailDumpsCount}++;

}

sub setDomainMailListContent{
  my ( $self, $domainId, $domainAsciiName, $path, $optPtr ) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my $mailContent = $self-&gt;{content_transport}-&gt;addDomainContent( 'domainmaillist', $domainId,
      'ml',
      'directory' =&gt; $path,
      'include'   =&gt; $optPtr-&gt;{'include'},
      'follow_symlinks' =&gt; $optPtr-&gt;{'follow_symlinks'},
      'sysuser' =&gt; $optPtr-&gt;{'sysuser'}
  );

  $root-&gt;getChild( 'maillists' )-&gt;getChild( 'content', 1, 1 )-&gt;addChild( $mailContent ) if $mailContent;
  @{$self-&gt;{domainMailListContent}-&gt;{$domainId}} = ( 'domainmaillist', $mailContent, $path ) if $mailContent;
}

sub setDomainPhostingContentCommon {
  my ( $self, $domainId, $domainName, $path, $contentType ) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my @phostings = $root-&gt;getChildren('phosting');
  if ( scalar(@phostings) &lt; 1 ) {
    Logging::warning('Unable to dump domain phosting content, because of dump XML structure is not full', 'PackerStructure');
    return;
  }

  my $cid_content = $self-&gt;{content_transport}-&gt;addDomainContent( $contentType, $domainId,
    $contentType,
    'directory' =&gt; $path
  );
  $phostings[0]-&gt;getChild( 'content', 1, 1 )-&gt;addChild( $cid_content ) if $cid_content;
  return $cid_content;
}

sub setDomainPhostingProtectedDirContent {
  my ( $self, $domainId, $domainName, $path ) = @_;
  $self-&gt;setDomainPhostingContentCommon($domainId, $domainName, $path, 'pd');
}

sub setDomainPhostingStatisticsContent {
  my ( $self, $domainId, $domainName, $path, $optPtr ) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my @phostings = $root-&gt;getChildren('phosting');
  if ( scalar(@phostings) &lt; 1 ) {
    Logging::warning('Unable to dump domain phosting statistics, because of dump XML structure is not full', 'PackerStructure');
    return;
  }

  my $cid_content = $self-&gt;{content_transport}-&gt;addDomainContent( 'statistics', $domainId,
    'statistics',
    'directory' =&gt; $path
  );
  $phostings[0]-&gt;getChild( 'content', 1, 1 )-&gt;addChild( $cid_content ) if $cid_content;
  @{$self-&gt;{domainStatistics}-&gt;{$domainId}} = ( 'statistics', $cid_content, $path )  if $cid_content;
}

sub setDomainPhostingWebstatContent {
  my ( $self, $domainId, $domainName, $path ) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my @phostings = $root-&gt;getChildren('phosting');
  if ( scalar(@phostings) &lt; 1 ) {
    Logging::warning('Unable to dump domain phosting webstat content, because of dump XML structure is not full', 'PackerStructure');
    return;
  }

  my $cid_webstat = $self-&gt;{content_transport}-&gt;addDomainContent( 'webstat', $domainId,
    'webstat',
    'directory' =&gt; $path
  );
  $phostings[0]-&gt;getChild( 'content', 1, 1 )-&gt;addChild( $cid_webstat ) if $cid_webstat;
}

sub setDomainPhostingWebstatSslContent {
  my ( $self, $domainId, $domainName, $path ) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my @phostings = $root-&gt;getChildren('phosting');
  if ( scalar(@phostings) &lt; 1 ) {
    Logging::warning('Error: setDomainPhostingWebstatSslContent: there are no node "phosting"', 'PackerStructure');
    return;
  }

  my $cid_webstat_ssl = $self-&gt;{content_transport}-&gt;addDomainContent( 'webstat_ssl', $domainId,
    'webstat-ssl',
    'directory' =&gt; $path
  );
  $phostings[0]-&gt;getChild( 'content', 1, 1 )-&gt;addChild( $cid_webstat_ssl ) if $cid_webstat_ssl;
}

sub setDomainPhostingFtpstatContent {
  my ( $self, $domainId, $domainName, $path ) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my @phostings = $root-&gt;getChildren('phosting');
  if ( scalar(@phostings) &lt; 1 ) {
    Logging::warning('Unable to dump domain phosting ftpstat content, because of dump XML structure is not full', 'PackerStructure');
    return;
  }

  my $cid_ftpstat = $self-&gt;{content_transport}-&gt;addDomainContent( 'ftp_stat', $domainId,
    'ftpstat',
    'directory' =&gt; $path
  );
  $phostings[0]-&gt;getChild( 'content', 1, 1 )-&gt;addChild( $cid_ftpstat ) if $cid_ftpstat;
}

sub setDomainPhostingLogsContent {
  my ( $self, $domainId, $domainName, $path ) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my @phostings = $root-&gt;getChildren('phosting');
  if ( scalar(@phostings) &lt; 1 ) {
    Logging::warning('Error: setDomainPhostingLogsContent: there are no node "phosting"', 'PackerStructure');
    return;
  }

  if ($self-&gt;{excludePatternsFile} and -e $self-&gt;{excludePatternsFile} and -s $self-&gt;{excludePatternsFile}) {
    # Prepare logs directory listing
    my ($fhListing, $listingFile) = File::Temp::tempfile(AgentConfig::getBackupTmpDir() . "/pmm-dplc-lst-XXXXXX", UNLINK =&gt; 1);
    chown getpwnam("root"), getgrnam("root"), $listingFile;
    chmod 0600, $listingFile;

    Logging::debug("List files in " . $path);
    $self-&gt;_listApacheAndUserFilesInFolder($path, $fhListing);
    close($fhListing);

    # Prepare temporary files for pmm-ras
    my ($fhChages, $changesFile) = File::Temp::tempfile(AgentConfig::getBackupTmpDir() . "/pmm-dplc-ch-XXXXXX", UNLINK =&gt; 1);
    my ($fhIndex, $indexFile) = File::Temp::tempfile(AgentConfig::getBackupTmpDir() . "/pmm-dplc-id-XXXXXX", UNLINK =&gt; 1);
    my ($fhExcludes, $excludesFile) = File::Temp::tempfile(AgentConfig::getBackupTmpDir() . "/pmm-dplc-ex-XXXXXX", UNLINK =&gt; 1);
    close($fhChages);
    close($fhIndex);
    close($fhExcludes);

    # Prepare excludes for logs directory
    my $res = HelpFuncs::replaceLinesInFile($self-&gt;{excludePatternsFile}, $excludesFile, '^\/logs\/|^logs\/', '');
    if ($res == 0) {
      my $cmd = [
        AgentConfig::pmmRasBin(), '--get-diff',
        '--listing-file', $listingFile,
        '--backup-file', $self-&gt;{storage}-&gt;{output_dir}."/".$self-&gt;getDomainsBackupPath($domainId, 'logs').".tgz",
        '--changes-file', $changesFile,
        '--index-file', $indexFile,
        '--exclude-patterns-file', $excludesFile
      ];

      if (Logging::getVerbosity() &gt;= Logging::LOG_LEVEL_DEBUG) {
        push (@{$cmd}, '--debug');
      }

      if (Logging::getVerbosity() &gt;= Logging::LOG_LEVEL_TRACE) {
        push (@{$cmd}, '--verbose');
      }

      Logging::debug("Execute: ".join(' ', @{$cmd}));
      my($err);
      run $cmd, '&gt;&amp;', \$err;

      my $dumpSucceed = 0;
      if ($?) {
        Logging::debug("Unable to apply exclusion pattern to log files, all log files will be dumped. Error (".$?.") ".$err, "LogsBackup");
      } else {
        my $cid_logs =  $self-&gt;{content_transport}-&gt;addDomainContent( 'logs', $domainId,
          'logs',
          'directory' =&gt; $path,
          'includes-file' =&gt; $changesFile,
          'no_recursion' =&gt; 1
        );
        $phostings[0]-&gt;getChild( 'content', 1, 1 )-&gt;addChild( $cid_logs ) if $cid_logs;
        $dumpSucceed = 1;
      }

      return if ($dumpSucceed);
    }
  }

  my $cid_logs =  $self-&gt;{content_transport}-&gt;addDomainContent( 'logs', $domainId,
    'logs',
    'directory' =&gt; $path
  );
  $phostings[0]-&gt;getChild( 'content', 1, 1 )-&gt;addChild( $cid_logs ) if $cid_logs;
}

sub setDomainPhostingAnonFtpstatContent {
  my ( $self, $domainId, $domainName, $path ) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my @phostings = $root-&gt;getChildren('phosting');
  if ( scalar(@phostings) &lt; 1 ) {
    Logging::warning('Error: setDomainPhostingAnonFtpstatContent: there are no node "phosting"', 'PackerStructure');
    return;
  }

  my $cid_anon_ftpstat = $self-&gt;{content_transport}-&gt;addDomainContent( 'anon_ftpstat', $domainId,
    'anon-ftpstat',
    'directory' =&gt; $path
  );
  $phostings[0]-&gt;getChild( 'content', 1, 1 )-&gt;addChild( $cid_anon_ftpstat ) if $cid_anon_ftpstat;
}

sub setDomainPhostingConfContent {
  my ( $self, $domainId, $domainName, $path, $optPtr ) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my @phostings = $root-&gt;getChildren('phosting');
  if ( scalar(@phostings) &lt; 1 ) {
    Logging::warning('Error: setDomainPhostingConfContent: there are no node "phosting"', 'PackerStructure');
    return;
  }

  my $cid_conf;
  $cid_conf = $self-&gt;{content_transport}-&gt;addDomainContent( 'conf', $domainId,
    'conf',
    'directory' =&gt; $path,
    'exclude' =&gt; $optPtr-&gt;{'exclude'}
  );
  $phostings[0]-&gt;getChild( 'content', 1, 1 )-&gt;addChild( $cid_conf ) if $cid_conf;
}

sub setDomainLogrotation {
  my ( $self, $domainId, $logRotationPtr) = @_;

  my %logRotation = %{$logRotationPtr};

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my $phosting = $root-&gt;getChild('phosting');
  if ( not $phosting ) {
    Logging::warning('Unable to dump domain log rotation settings, because of dump XML structure is not full', 'PackerStructure');
    return;
  }

  my $node;
  if (keys %logRotation) {
    $self-&gt;makeLogrotationNode( $phosting-&gt;getChild( 'preferences', 1 ), \%logRotation );
  }
}

sub setDomainAnonFtp {
  my ( $self, $domainId, $domainName, $propsPtr, $pub_path, $incoming_path, $optPtr ) = @_;

  my %props = %{$propsPtr};

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my $phosting = $root-&gt;getChild('phosting');
  if ( not $phosting ) {
    Logging::warning('Error: setDomainAnonFtp: there are no node "phosting"', 'PackerStructure');
    return;
  }

  my $anonRoot = XmlNode-&gt;new('anonftp');
  if ( $props{'status'} =~ /true/ ) {
    $anonRoot-&gt;setAttribute( 'pub', 'true' );
  }
  if ( $props{'incoming'} =~ /true/ ) {
    $anonRoot-&gt;setAttribute( 'incoming', 'true' );
  }
  if ( defined( $props{'max_conn'} ) ) {
    makeAnonftpLimitNode( $anonRoot, 'max-connections',
      $props{'max_conn'} );
  }
  if ( defined( $props{'bandwidth'} ) ) {
    makeAnonftpLimitNode( $anonRoot, 'bandwidth',
      $props{'bandwidth'} );
  }
  if ( defined( $props{'quota'} ) ) {
    makeAnonftpLimitNode( $anonRoot, 'incoming-disk-quota',
      $props{'quota'} );
  }
  if ( defined( $props{'display_login'} ) ) {
    $anonRoot-&gt;setAttribute( 'display-login', $props{'display_login'} );
  }
  if ( $props{'incoming_readable'} =~ /true/ ) {
    makeAnonftpPermissionNode( $anonRoot, 'incoming-download' );
  }
  if ( $props{'incoming_subdirs'} =~ /true/ ) {
    makeAnonftpPermissionNode( $anonRoot, 'incoming-mkdir' );
  }
  if ( defined( $props{'login_text'} ) ) {
    my $loginMessageNode =
      XmlNode-&gt;new( 'login-message',
      'content' =&gt; $props{'login_text'} );
    $anonRoot-&gt;addChild($loginMessageNode);
  }

  $phosting-&gt;getChild( 'preferences', 1 )-&gt;addChild($anonRoot);
}

sub addDomainProtectedDir {
  my ( $self, $domainId, $pdirPath, $pdirTitle, $pdirNonSSL, $pdirSSL, $pdirCGI, $pdirUsersPtr) = @_;

  my @pdirUsers = @{$pdirUsersPtr};

  my $parent = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $parent;

  my $phostingNode = $parent-&gt;getChild('phosting');
  unless ( defined $phostingNode ) {
    Logging::warning('Error: addDomainProtectedDir: there are no node "phosting"', 'PackerStructure');
    return;
  }

  my $pdirNode = XmlNode-&gt;new('pdir');

  # workaround of CLI inabliity to create '' directory.
  if ( $pdirPath eq '' ) {
    $pdirPath = '/';
  }

  $pdirNode-&gt;setAttribute( 'name', $pdirPath );
  if ($pdirTitle) {
    $pdirNode-&gt;setAttribute( 'title', $pdirTitle );
  }
  if ($pdirNonSSL) {
    $pdirNode-&gt;setAttribute( 'nonssl', $pdirNonSSL );
  }
  if ($pdirSSL) {
    $pdirNode-&gt;setAttribute( 'ssl', $pdirSSL );
  }
  if ($pdirCGI) {
    $pdirNode-&gt;setAttribute( 'cgi', $pdirCGI );
  }

  my $userNode;
  my $item;
  for my $user (@pdirUsers) {
    $userNode = XmlNode-&gt;new('pduser');
    $pdirNode-&gt;addChild($userNode);
    $userNode-&gt;setAttribute( 'name', $user-&gt;{'login'} );

    $item = CommonPacker::makePasswordNode( $user-&gt;{'passwd'}, CommonPacker::normalizePasswordType( $user-&gt;{'passwdType'} ) );
    $userNode-&gt;addChild($item);
  }

  $phostingNode-&gt;getChild( 'preferences', 1 )-&gt;addChild($pdirNode);
}

sub addDomainSubFtpUser {
  my ( $self, $domainId, $domainName, $sysuserPtr, $ptrFtpUser) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my $phostingNode = $root-&gt;getChild('phosting');

  my $ftpuserNode = XmlNode-&gt;new('ftpuser');
  $ftpuserNode-&gt;setAttribute('name', $sysuserPtr-&gt;{'login'});
  $ftpuserNode-&gt;setAttribute('external-id', $ptrFtpUser-&gt;{'external_id'}) if defined $ptrFtpUser-&gt;{'external_id'} and $ptrFtpUser-&gt;{'external_id'} ne '';
  $ftpuserNode-&gt;addChild($self-&gt;makeSysUser($sysuserPtr));
  $phostingNode-&gt;getChild( 'ftpusers', 1 )-&gt;addChild($ftpuserNode);
}

sub setEmptySubFtpUsersNode {
  my ($self, $domainId) = @_;
  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my $phostingNode = $root-&gt;getChild('phosting', 1);

  $phostingNode-&gt;getChild('ftpusers', 1);
}

sub removeResellerChildNodeIfEmpty {
  my ( $self, $clientId, $nodeName ) = @_;
  my $root = $self-&gt;getCashedClientNode( $clientId );
  return unless defined $root;

  my $containerNode = $root-&gt;getChild( $nodeName );
  if ( defined $containerNode &amp;&amp; not $containerNode-&gt;getChildren() ) {
    $root-&gt;removeChildren( $nodeName );
  }
}

sub removePhostingChildNodeIfEmpty {
  my ( $self, $domainId, $nodeName ) = @_;
  my $root = $self-&gt;getCashedDomainNode( $domainId );
  return unless defined $root;

  my $phostingNode = $root-&gt;getChild( 'phosting', 1 );

  my $containerNode = $phostingNode-&gt;getChild( $nodeName . 's' );
  if ( defined $containerNode &amp;&amp; not $containerNode-&gt;getChildren( $nodeName ) ) {
    $phostingNode-&gt;removeChildren( $nodeName . 's' );
  }
}

sub removeMailSystemChildNodeIfEmpty {
  my ( $self, $domainId, $nodeName ) = @_;
  my $root = $self-&gt;getCashedDomainNode( $domainId );
  return unless defined $root;

  my $mailsystemNode = $root-&gt;getChild( 'mailsystem' );

  my $containerNode = $mailsystemNode-&gt;getChild( $nodeName . 's' );
  if ( defined $containerNode &amp;&amp; not $containerNode-&gt;getChildren( $nodeName ) ) {
    $mailsystemNode-&gt;removeChildren( $nodeName . 's' );
  }
}

sub addDomainWebUser {
  my ( $self, $domainId, $domainName, $sysuserPtr, $scriptingPtr, $webUserHome, $privatePath ) = @_;

  my %sysuser = %{$sysuserPtr};
  my %scripting = %{$scriptingPtr};

  my $parent = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $parent;

  my $phostingNode = $parent-&gt;getChild('phosting');
  unless( defined $phostingNode ) {
    Logging::warning('Unable to dump domain webuser preferences, because of dump XML structure is not full', 'PackerStructure');
    return;
  }

  my $webuserNode = XmlNode-&gt;new('webuser');

  $webuserNode-&gt;addChild($self-&gt;makeSysUser(\%sysuser));

  my $userName = $sysuser{'login'};
  $webuserNode-&gt;setAttribute( 'name', $userName );

  my %webUserScripting = (
    'ssi'         =&gt; 'ssi',
    'php'         =&gt; 'php',
    'cgi'         =&gt; 'cgi',
    'perl'        =&gt; 'perl',
    'asp'         =&gt; 'asp',
    'python'      =&gt; 'python',
    'asp_dot_net' =&gt; 'asp_dot_net',
    'fastcgi'     =&gt; 'fastcgi',
  );

  my $item = XmlNode-&gt;new('scripting');
  while ( my ( $xmlName, $fieldName ) = each(%webUserScripting) ) {
    if ( defined $scripting{$fieldName}
      and ( $scripting{$fieldName} eq 'true' or $scripting{$fieldName} eq 'false' ) )
    {
      $item-&gt;setAttribute( $xmlName, $scripting{$fieldName} );
    }
  }

  if (exists $scripting{'write_modify'} &amp;&amp; defined $scripting{'write_modify'}) {
    $item-&gt;setAttribute('write_modify', $scripting{'write_modify'}) ;
  }

  $webuserNode-&gt;addChild($item);

  $phostingNode-&gt;getChild( 'webusers', 1 )-&gt;addChild($webuserNode);
}

sub setDomainWebalizer {
  my ( $self, $domainId, $directRef, $hiddenRefsPtr, $groupRefsPtr) = @_;

  my @hiddenRefs = @{$hiddenRefsPtr};
  my @groupRefs = @{$groupRefsPtr};

  my $parent = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $parent;

  my $phostingNode = $parent-&gt;getChild('phosting');
  unless( defined $phostingNode ) {
    Logging::warning('Unable to dump domain webalizer settings, because of dump XML structure is not full', 'PackerStructure');
    return;
  }

  my $webalizerNode = XmlNode-&gt;new("webalizer");

  if ($directRef)
  {
    $webalizerNode-&gt;setAttribute( 'hide-direct-referrer', 'true' );
  }

  for my $ref (@hiddenRefs) {
    $webalizerNode-&gt;addChild(
      XmlNode-&gt;new(
        "webalizer-hidden-referrer", 'content' =&gt; $ref
      )
    );
  }

  for my $groupRef (@groupRefs ) {
    $webalizerNode-&gt;addChild(
      XmlNode-&gt;new(
        'webalizer-group-referrer',
        'content'    =&gt; $groupRef-&gt;{'ref'},
        'attributes' =&gt; { 'group-name' =&gt; $groupRef-&gt;{'name'} }
      )
    );
  }

  $phostingNode-&gt;getChild( 'preferences', 1 )-&gt;addChild($webalizerNode);
}


sub setComposerInstances {
  my ($self, $domainId, $embeddedInfo) = @_;

  return unless defined($embeddedInfo-&gt;{'composer-instances'});

  my $domainNode = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $domainNode;

  my ($composerInstances) = @{$embeddedInfo-&gt;{'composer-instances'}};
  $self-&gt;addEmbeddedInfo($domainNode, 'composer-instances', $composerInstances);
}

sub setDomainPerfomance {
  my ( $self, $domainId, $max_connection, $traffic_bandwidth) = @_;

  my $parent = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $parent;

  my $phostingNode = $parent-&gt;getChild('phosting');
  unless ( defined $phostingNode ) {
    Logging::warning('Unable to dump domain performance settings, because of dump XML structure is not full', 'PackerStructure');
    return;
  }

  my $perfomanceNode = XmlNode-&gt;new('perfomance');
  $perfomanceNode-&gt;addChild(
    XmlNode-&gt;new(
      'max-connections', 'content' =&gt; $max_connection
    )
  );
  $perfomanceNode-&gt;addChild(
    XmlNode-&gt;new(
      'traffic-bandwidth', 'content' =&gt; $traffic_bandwidth
    )
  );

  $phostingNode-&gt;getChild( 'preferences', 1 )-&gt;addChild( $perfomanceNode );
}

sub appendNodeToPhosting {
  my ( $self, $domainId, $rawXml ) = @_;

  my $parent = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $parent;

  my $phostingNode = $parent-&gt;getChild('phosting');
  unless ( defined $phostingNode ) {
    Logging::warning('Error: appendNodeToPhosting: there are no node "phosting"', 'PackerStructure');
    return;
  }

  $phostingNode-&gt;addChild(XmlNode-&gt;new(undef, 'raw' =&gt; $rawXml));
}

sub setIisAppPool {
  my ( $self, $domainId, $info ) = @_;

  my $parent = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $parent;

  my $phostingNode = $parent-&gt;getChild('phosting');
  unless ( defined $phostingNode ) {
    Logging::warning('Error: setIisAppPool: there are no node "phosting"', 'PackerStructure');
    return;
  }

  my $phostingPreferencesNode = $phostingNode-&gt;getChild('preferences');
  unless ( defined $phostingPreferencesNode ) {
    Logging::warning('Error: setIisAppPool: there are no node "phosting/preferences"', 'PackerStructure');
    return;
  }

  $phostingPreferencesNode-&gt;addChild(XmlNode-&gt;new(undef, 'raw' =&gt; $info));
}


sub setDomainWebStat{
  my ( $self, $domainId, $stat_ttl) = @_;

  my $parent = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $parent;

  my $phostingNode = $parent-&gt;getChild('phosting');
  unless( defined $phostingNode ) {
    Logging::warning('Error: setDomainWebStat: there are no node "phosting"', 'PackerStructure');
    return;
  }
  my $webstatNode = XmlNode-&gt;new('web-stat');
  $webstatNode-&gt;setAttribute( 'stat-ttl', $stat_ttl ) if $stat_ttl;
  $phostingNode-&gt;getChild( 'preferences', 1 )-&gt;addChild( $webstatNode );
}

sub setDomainShosting {
  my ( $self, $domainId, $forward, $ips) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my $shostingNode = XmlNode-&gt;new( 'shosting');
  $shostingNode-&gt;addChild(XmlNode-&gt;new('url', 'content' =&gt; $forward-&gt;{'redirect'}));

  my $propertiesNode = $shostingNode-&gt;getChild('properties', 1);

  foreach my $ip (keys %{$ips}) {
    my $ipNode = $self-&gt;makeIpNode($ip, $ips-&gt;{$ip});
    $propertiesNode-&gt;addChild($ipNode);
  }

  if (defined ($forward-&gt;{'http_code'})) {
	my $httpcodeNode = XmlNode-&gt;new('httpcode', 'content' =&gt; $forward-&gt;{'http_code'});
	$shostingNode-&gt;addChild($httpcodeNode);
  }

  $root-&gt;addChild($shostingNode);
}

sub setDomainFhosting {
  my ( $self, $domainId, $forward, $ips) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my $fhostingNode = XmlNode-&gt;new( 'fhosting');
  $fhostingNode-&gt;addChild(XmlNode-&gt;new('url', 'content' =&gt; $forward));

  my $propertiesNode = $fhostingNode-&gt;getChild('properties', 1);

  foreach my $ip (keys %{$ips}) {
    my $ipNode = $self-&gt;makeIpNode($ip, $ips-&gt;{$ip});
    $propertiesNode-&gt;addChild($ipNode);
  }

  $root-&gt;addChild($fhostingNode);
}

sub addSite {
  my ( $self, $domainId, $sitePtr) = @_;

  my $parent = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $parent;

  my $phostingNode = $parent-&gt;getChild('phosting');
  unless ( defined $phostingNode ) {
    Logging::warning('Error: addSite: there are no node "phosting"', 'PackerStructure');
    return;
  }

  my $siteNode = XmlNode-&gt;new( 'site' );

  $phostingNode-&gt;getChild( 'sites', 1 )-&gt;addChild($siteNode);

}

###### SubDomain functions ######

sub addSubDomain {
  my ( $self, $domainId, $ptrSubDomain, $subDomainName, $subAsciiDomainName, $https, $shared_content, $sysuserPtr, $scriptingPtr) = @_;
  $subAsciiDomainName = $subDomainName if not $subAsciiDomainName;
  my $subDomainId = $ptrSubDomain-&gt;{'id'};
  $self-&gt;regSubdomainObjectBackupPath( $self-&gt;getPhostingBackupPath( $domainId ), $subDomainId, $subAsciiDomainName, $domainId );

  my %sysuser = %{$sysuserPtr};
  my %scripting = %{$scriptingPtr};

  my $parent = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $parent;

  my $phosting = $parent-&gt;getChild('phosting');
  if ( not $phosting ) {
    Logging::warning('Error: addSubdomain: there are no node "phosting"', 'PackerStructure');
    return;
  }

  my $root = XmlNode-&gt;new('subdomain', 'attributes' =&gt; {'id' =&gt; $subDomainId});
  $self-&gt;{subDomainNodes}-&gt;{$subDomainId} = $root;
  my $parentGuid = $parent-&gt;getAttribute('guid');
  $root-&gt;setAttribute( "guid", $self-&gt;getSubdomainGuid( $parentGuid, $subDomainId ) ) if $parentGuid;
  my $phostingGuid = $phosting-&gt;getAttribute('guid');
  $root-&gt;setAttribute( 'owner-guid', $phostingGuid ) if $phostingGuid;

  $root-&gt;setAttribute( 'name', $subDomainName );

  if ( 'true' eq $https ) {
    $root-&gt;setAttribute( 'https', 'true' );
  }

  if ( $shared_content ne '' ) {
    $root-&gt;setAttribute( 'shared-content', $shared_content );
  }

  if ( exists $ptrSubDomain-&gt;{'www-root'} ) {
    $root-&gt;setAttribute( 'www-root', $ptrSubDomain-&gt;{'www-root'} );
  }

  if ( exists $ptrSubDomain-&gt;{'certificate_ref'} ) {
    $root-&gt;setAttribute( 'certificate', $ptrSubDomain-&gt;{'certificate_ref'});
  }

  if ( exists $ptrSubDomain-&gt;{'original-conf-directory'} ) {
    $root-&gt;setAttribute('original-conf-directory', $ptrSubDomain-&gt;{'original-conf-directory'});
  }

  ## %sysuser ##

  if (%sysuser)
  {
    $root-&gt;addChild($self-&gt;makeSysUser(\%sysuser));
  }

  ## %scripting ##

  my $scripringItem = XmlNode-&gt;new('scripting');
  while ( my ( $xmlName, $value ) = each(%scripting) ) {
      $scripringItem-&gt;setAttribute( $xmlName, $value );
  }
  $root-&gt;addChild($scripringItem);

  $phosting-&gt;getChild( 'subdomains', 1 )-&gt;addChild($root);

}

sub setSubDomainHttpdocsContent {
  my ( $self, $subDomainId, $path, $exclude_httpdocs_files_ptr, $webspaceId ) = @_;

  my @exclude_httpdocs_files = @{$exclude_httpdocs_files_ptr};

  my $root = $self-&gt;{subDomainNodes}-&gt;{$subDomainId};

  my $cid_docroot = $self-&gt;{content_transport}-&gt;addSubDomainPhostingContent( 'docroot', $subDomainId, $webspaceId,
    "httpdocs",
    "directory" =&gt; $path,
    "exclude"   =&gt; \@exclude_httpdocs_files
  );
  $root-&gt;getChild( 'content', 1, 1 )-&gt;addChild( $cid_docroot ) if $cid_docroot;
}

sub setSubDomainHttpsdocsContent {
  my ( $self, $subDomainId, $path, $exclude_httpsdocs_files_ptr ) = @_;

  my @exclude_httpsdocs_files = @{$exclude_httpsdocs_files_ptr};

  my $root = $self-&gt;{subDomainNodes}-&gt;{$subDomainId};

  my $cid_docroot_ssl = $self-&gt;{content_transport}-&gt;addSubDomainPhostingContent('docroot_ssl', $subDomainId, undef,
    "httpsdocs",
    "directory" =&gt; $path,
    "exclude"   =&gt; \@exclude_httpsdocs_files
  );
  $root-&gt;getChild( 'content', 1, 1 )-&gt;addChild( $cid_docroot_ssl ) if $cid_docroot_ssl;
}

sub setSubDomainErrorDocsContent {
  my ( $self, $subDomainId, $path ) = @_;
  my $subdomainNode = $self-&gt;{subDomainNodes}-&gt;{$subDomainId};

  my $cid_conf = $self-&gt;{content_transport}-&gt;addSubDomainPhostingContent( 'error_docs', $subDomainId, undef,
    "error-docs",
    "directory" =&gt; $path
  );
  $subdomainNode-&gt;getChild( 'content', 1, 1 )-&gt;addChild( $cid_conf ) if $cid_conf;

}

sub setSubDomainConfContent {
  my ( $self, $subDomainId, $path ) = @_;

  my $root = $self-&gt;{subDomainNodes}-&gt;{$subDomainId};

  my $cid_conf = $self-&gt;{content_transport}-&gt;addSubDomainPhostingContent( 'conf', $subDomainId, undef,
    "conf",
    "directory" =&gt; $path
  );
  $root-&gt;getChild( 'content', 1, 1 )-&gt;addChild( $cid_conf ) if $cid_conf;
}
###### End SubDomain functions ######

####### Mail functions #######

sub addMail {
    my ( $self, $domainId, $mailId, $mailName, $passwd, $typePasswd, $userUid, $cpAccessDefault ) = @_;

    $self-&gt;regMailnameObjectBackupPath( $self-&gt;getDomainsBackupPath( $domainId ), $mailId, $mailName, $domainId );

    my $parent = $self-&gt;getCashedDomainNode($domainId);
    return unless defined $parent;

    my $mailService = $parent-&gt;getChild('mailsystem');
    if ( not $mailService ) {
      Logging::warning("Error: Packer.addMail: there are no node 'mailsystem'", 'PackerStructure');
      return;
    }

    my $root = XmlNode-&gt;new( 'mailuser', 'attributes' =&gt; {
        'id'   =&gt; $mailId,
        'name' =&gt; $mailName
        } );

    if (defined $userUid) {
      $root-&gt;setAttribute('user-guid', $userUid);
    }
    
    if (defined $cpAccessDefault) {
      $root-&gt;setAttribute('cp-access-default', $cpAccessDefault);
    }

    my $parentGuid = $parent-&gt;getAttribute('guid');
    $root-&gt;setAttribute( 'guid', $self-&gt;getMailnameGuid( $parentGuid, $mailId ) ) if $parentGuid;
    $root-&gt;setAttribute( 'owner-guid', $parentGuid ) if $parentGuid;

    my $props = $root-&gt;getChild( 'properties', 1 );
    $root-&gt;getChild( 'preferences', 1 );

    my $item;
    if ( defined($passwd) &amp;&amp; $passwd ) {
      if ( $passwd =~ /NULL/ ) {
        $item = CommonPacker::makePasswordNode( '', 'plain' );
      }
      else {
        $item = CommonPacker::makePasswordNode( $passwd, $typePasswd );
      }

      $props-&gt;addChild( $item );
    }

    $self-&gt;{mailNodes}-&gt;{$mailId} = $root;

    $mailService-&gt;getChild( 'mailusers', 1 )-&gt;addChild($root);
}

sub setMailBoxQuota {
    my ( $self, $mailId, $mbox_quota ) = @_;

    my $root = $self-&gt;{mailNodes}-&gt;{$mailId};

    $root-&gt;setAttribute( 'mailbox-quota', $mbox_quota );
}

sub setMailBox {
    my ( $self, $mailId, $mailName, $domainAsciiName, $enabled, $path ) = @_;

    my $root = $self-&gt;{mailNodes}-&gt;{$mailId};
    if ( !defined($root) ) {
      Logging::warning('Unable to dump $mailName mailbox settings, because of dump XML structure is not full', 'PackerStructure');
      return;
    }

    my $item = XmlNode-&gt;new( 'mailbox', 'attributes' =&gt; { 'type' =&gt; 'mdir' } );
    $root-&gt;getChild( 'preferences', 1 )-&gt;addChild($item);

    $item-&gt;setAttribute( 'enabled', $enabled );

    my $cid = $self-&gt;{content_transport}-&gt;addMailnameContent( 'mailbox', $mailId, "mdir",
      'directory' =&gt; $path, 'include_hidden_files' =&gt; 1 );
    $item-&gt;getChild( 'content', 1, 1 )-&gt;addChild( $cid ) if $cid;
}

sub addMailAliase {
    my ( $self, $mailId, $name ) = @_;

    my $root = $self-&gt;{mailNodes}-&gt;{$mailId};
    if ( !defined($root) ) {
      Logging::warning('Unable to dump $name mail alias settings, because of dump XML structure is not full', 'PackerStructure');
      return;
    }

    my $item = XmlNode-&gt;new( 'alias', 'content' =&gt; $name );
    $root-&gt;getChild( 'preferences', 1 )-&gt;addChild($item);
}

sub setMailForwarding {
    my ( $self, $mailId, $enabled, $membersPtr ) = @_;

    unless ( ref($membersPtr) =~ /ARRAY/ ) {
      Logging::warning("Error: setMailForwarding: membersPtr is not ref array",'assert');
      return;
    }

    my @members = @{$membersPtr};

    my $root = $self-&gt;{mailNodes}-&gt;{$mailId};
    if ( !defined($root) ) {
      Logging::warning('Unable to dump mail forwarding settings, because of dump XML structure is not full', 'PackerStructure');
      return;
    }

    $root-&gt;setAttribute( 'forwarding-enabled', $enabled? 'true': 'false' );

    my $item;
    foreach my $member (@members) {
      $item = XmlNode-&gt;new( 'forwarding', 'content' =&gt; $member );
      $root-&gt;getChild( 'preferences', 1 )-&gt;addChild($item);
    }
}

sub setMailAutoresponders {
    my ( $self, $mailId, $mailName, $domainAsciiName, $dir, $enabled, $autorespondersPtr, $attachesPtr ) = @_;

    unless ( ref($autorespondersPtr) =~ /ARRAY/ ) {
      Logging::warning("Error: setMailAutoresponders: autorespondersPtr is not ref array",'assert');
      return;
    }
    my @autoresponders = @{$autorespondersPtr};

    unless ( ref($attachesPtr) =~ /ARRAY/ ) {
      Logging::warning("Error: setMailAutoresponders: attachesPtr is not ref array",'assert');
      return;
    }
    my @attaches = @{$attachesPtr};

    my $root = $self-&gt;{mailNodes}-&gt;{$mailId};
    if ( !defined($root) ) {
      Logging::warning('Error: setMailAutoresponders: empty parent node', 'PackerStructure');
      return;
    }

    my $autorespondersNode = XmlNode-&gt;new( 'autoresponders' );

    my $cid = $self-&gt;{content_transport}-&gt;addMailnameContent( 'attaches', $mailId,  "attach",
      "directory" =&gt; $dir, 'checkEmptyDir' =&gt; 1 );
    $autorespondersNode-&gt;getChild( 'content', 1, 1 )-&gt;addChild( $cid ) if $cid;

    foreach my $file (@attaches) {
      $autorespondersNode-&gt;addChild(
        XmlNode-&gt;new( 'attach', 'attributes' =&gt; { 'file' =&gt; $file } ) );
    }

    foreach my $autoresponder (@autoresponders) {
      my $node = $self-&gt;makeAutoresponderNode ($enabled, $autoresponder, $mailName);
      $autorespondersNode-&gt;addChild($node);
    }

    $root-&gt;getChild( 'preferences', 1 )-&gt;addChild($autorespondersNode);
}

sub setMailAddressbook {
    my ( $self, $mailId, $paramsPtr, $turbaVersion ) = @_;

    my @params = @{$paramsPtr};

    my $parent = $self-&gt;{mailNodes}-&gt;{$mailId};
    if ( !defined($parent) ) {
      Logging::warning('Unable to dump mailbox addressbook, because of dump XML structure is not full', 'PackerStructure');
      return;
    }

    my $node = XmlNode-&gt;new('addressbook');

    my %objectFields = (
      'id'           =&gt; 'id',
      'name'         =&gt; 'name',
      'alias'        =&gt; 'alias',
      'email'        =&gt; 'email',
      'title'        =&gt; 'title',
      'company'      =&gt; 'company',
      'home-phone'   =&gt; 'homephone',
      'work-phone'   =&gt; 'workphone',
      'mobile-phone' =&gt; 'cellphone',
      'fax'          =&gt; 'fax',
      'home-address' =&gt; 'homeaddress',
      'work-address' =&gt; 'workaddress',
      'notes'        =&gt; 'notes'
      );

    if ($turbaVersion-&gt;{'majorVersion'} = 2 &amp;&amp; $turbaVersion-&gt;{'minorVersion'} &gt; 2 ) {
        $objectFields{'name'} = 'lastname';
        $objectFields{'home-address'} = 'homestreet';
        $objectFields{'work-address'} = 'workstreet';
        $objectFields{'first-name'} = 'firstname';
        $objectFields{'middle-names'} = 'middlenames';
    }

    foreach my $ptrHash (@params) {
      if ( $ptrHash-&gt;{'object_type'} eq 'Group' ) {

        my $group =
          XmlNode-&gt;new( 'addressbook-group',
          'attributes' =&gt; { 'id' =&gt; $ptrHash-&gt;{'object_id'} } );

        my $members = $ptrHash-&gt;{'object_members'};
        while ( $members =~ /"(.*?)"/g ) {
          my $member = $1;
          chomp $member;

          $group-&gt;addChild(
            XmlNode-&gt;new(
              'addressbook-member', 'attributes' =&gt; { 'id' =&gt; $member }
            )
          );
        }

        $node-&gt;addChild($group);
      }
      else {
        my $user = XmlNode-&gt;new('addressbook-contact');
        my ( $field, $attr );
        while ( ( $field, $attr ) = each %objectFields ) {
          if ( defined $ptrHash-&gt;{ 'object_' . $attr } ) {

            # Here 'encoded' attribute means there is no meaning to
            # convert data to UTF as it was already converted manually
            my $value = $ptrHash-&gt;{ 'object_' . $attr };
            $value = $self-&gt;{base64}-&gt;{'ENCODE'}-&gt;($value) if $attr ne 'id';
            $user-&gt;setAttribute( $field, $value );
          }
        }
        $node-&gt;addChild($user);
      }
    }

    $parent-&gt;getChild( 'preferences', 1 )-&gt;addChild($node);
}

sub setMailSpamSettings {
    my ( $self, $mailId, $mailName, $domainAsciiName, $status, $server_conf,
      $action, $requiredScore, $modify_subj, $subj_text,
      $blackListPtr, $whiteListPtr, $unblackListPtr, $unwhiteListPtr, $path, $server ) = @_;

    my @blackList = @{$blackListPtr};
    my @whiteList = @{$whiteListPtr};
    my @unblackList = @{$unblackListPtr};
    my @unwhiteList = @{$unwhiteListPtr};

    my $parent;
    if (defined($mailId)) {
    	$parent = $self-&gt;{mailNodes}-&gt;{$mailId};
    }elsif (defined($server)) {
    	$parent = $self-&gt;{serverNode};
    }
    if ( !defined($parent) ) {
      Logging::warning('Unable to dump SPAM filter settings, because of dump XML structure is not full', 'PackerStructure');
      return;
    }

    my $item = XmlNode-&gt;new( 'spamassassin' );

    $item-&gt;setAttribute( 'status', $status ) if defined($status);
    $item-&gt;setAttribute( 'action', $action ) if ( defined($action) &amp;&amp; $action );
    $item-&gt;setAttribute( 'server-conf', $server_conf )
      if ( defined($server_conf) &amp;&amp; $server_conf );
    $item-&gt;setAttribute( 'hits', $requiredScore )
      if ( defined($requiredScore) &amp;&amp; $requiredScore );
    $item-&gt;setAttribute( 'modify-subj', $modify_subj )
      if ( defined($modify_subj) &amp;&amp; $modify_subj );
    $item-&gt;setAttribute( 'subj-text', $subj_text )
      if ( defined($subj_text) &amp;&amp; $subj_text );
    $item-&gt;setAttribute( 'max-spam-threads', $server-&gt;{'spamfilter_max_children'})
      if ( defined($server-&gt;{'spamfilter_max_children'}) &amp;&amp; $server-&gt;{'spamfilter_max_children'});

    foreach my $blMail (@blackList) {
      $item-&gt;addChild( XmlNode-&gt;new( 'blacklist-member', 'content' =&gt; $blMail ) );
    }
    foreach my $wtMail (@whiteList) {
      $item-&gt;addChild( XmlNode-&gt;new( 'whitelist-member', 'content' =&gt; $wtMail ) );
    }
    foreach my $ublMail (@unblackList) {
      $item-&gt;addChild(
        XmlNode-&gt;new( 'unblacklist-member', 'content' =&gt; $ublMail ) );
    }
    foreach my $uwtMail (@unwhiteList) {
      $item-&gt;addChild(
        XmlNode-&gt;new( 'unwhitelist-member', 'content' =&gt; $uwtMail ) );
    }

    if (defined($mailId) &amp;&amp; -d "$path") {
      my $cid = $self-&gt;{content_transport}-&gt;addMailnameContent( 'spam-assasin', $mailId, "sa", "directory" =&gt; $path );
      $item-&gt;getChild( 'content', 1, 1 )-&gt;addChild( $cid ) if $cid;
    }

    if (defined($mailId)) {
	    $parent-&gt;getChild( 'preferences', 1 )-&gt;addChild($item);
    }elsif(defined($server)) {
    	    $parent-&gt;addChild($item);
    }
}

sub setMailVirusSettings {
    my ( $self, $mailId, $state ) = @_;

    my $parent = $self-&gt;{mailNodes}-&gt;{$mailId};
    if ( !defined($parent) ) {
      Logging::warning('Unable to dump virus protection settings, because of dump XML structure is not full', 'PackerStructure');
      return;
    }

    my $item = XmlNode-&gt;new('virusfilter');
    $item-&gt;setAttribute( 'state', $state );

    $parent-&gt;getChild( 'preferences', 1 )-&gt;addChild($item);
}

sub addMailCustomButton {
    my ( $self, $mailId, $id, $optionsPtr, $customButtonsDir, $icon ) = @_;

    my $parent = $self-&gt;{mailNodes}-&gt;{$mailId};
    if ( !defined($parent) ) {
      Logging::warning('Unable to dump mail custom buttons settings, because of dump XML structure is not full', 'PackerStructure');
      return;
    }

    my $node = $self-&gt;makeCustomButtonNode( 'mails', $mailId, $id, $optionsPtr, $customButtonsDir, $icon );

    $parent-&gt;getChild( 'preferences', 1 )-&gt;addChild($node);
}
####### End Mail functions #######

####### Siteapps functions #######

sub addDomainSapp {
  my ( $self, $domainId, $sappId, $sapp, $licenseType ) = @_;
  my $parent = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $parent;

  my $phosting = $parent-&gt;getChild('phosting');
  if ( not $phosting ) {
    Logging::warning('Unable to dump domain site applications, because of dump XML structure is not full','assert');
    return;
  }

  my $sapp_installed = $self-&gt;makeSappNode($sappId, $sapp, $licenseType);

  $self-&gt;{sappNodes}-&gt;{$sappId} = $sapp_installed;
  $phosting-&gt;getChild( 'applications', 1 )-&gt;addChild($sapp_installed);
}

sub addSubDomainSapp {
  my ( $self, $subDomainId, $sappId, $sapp, $licenseType ) = @_;
  my $root = $self-&gt;{subDomainNodes}-&gt;{$subDomainId};

  my $sapp_installed = $self-&gt;makeSappNode( $sappId, $sapp, $licenseType );

  $self-&gt;{sappNodes}-&gt;{$sappId} = $sapp_installed;
  $root-&gt;getChild( 'applications', 1 )-&gt;addChild($sapp_installed);
}

sub setSappParams {
  my ( $self, $sappId, $sapp ) = @_;

  my $paramsPtr = $sapp-&gt;getParams();

  my %params = %{$paramsPtr};

  my $sapp_installed = $self-&gt;{sappNodes}-&gt;{$sappId};

  while ( my ( $param_name, $param_value ) = each %params )
  {
    my $name;
    my $value;
    if ( $sapp-&gt;encodedParams() ) {
      $name = $param_name;
      $value = $param_value;
    }
    else {
      $name = $self-&gt;{base64}-&gt;{'ENCODE'}-&gt;($param_name);
      $value = $self-&gt;{base64}-&gt;{'ENCODE'}-&gt;($param_value);
    }

    $sapp_installed-&gt;addChild(
      XmlNode-&gt;new(
        'sapp-param',
        'children' =&gt; [
          XmlNode-&gt;new(
            'sapp-param-name',
            'attributes' =&gt; { 'encoding' =&gt; 'base64' },
            'content'    =&gt; $name
          ),
          XmlNode-&gt;new(
            'sapp-param-value',
            'attributes' =&gt; { 'encoding' =&gt; 'base64' },
            'content'    =&gt; $value
          )
        ]
      )
    );
  }
}

sub setSappSettings {
  my ( $self, $sappId, $sapp ) = @_;

  my $settingsPtr = $sapp-&gt;getSettings();

  if (scalar keys %{$settingsPtr} &gt; 0) {

    my %settings = %{$settingsPtr};

    my $sappInstalledNode = $self-&gt;{sappNodes}-&gt;{$sappId};

    my $sappSettingsNode = XmlNode-&gt;new('sapp-settings');

    while ( my ( $setting_name, $setting_value ) = each %settings )
    {
      $sappSettingsNode-&gt;addChild(
        XmlNode-&gt;new(
          'setting',
          'children' =&gt; [
            XmlNode-&gt;new(
              'name',
              'content'    =&gt; $setting_name
            ),
            XmlNode-&gt;new(
              'value',
              'content'    =&gt; $setting_value
            )
          ]
        )
      );
    }
    $sappInstalledNode-&gt;addChild($sappSettingsNode);
  }
}

sub setSappEntryPoints {
  my ( $self, $sappId, $sapp ) = @_;

  my $sapp_installed = $self-&gt;{sappNodes}-&gt;{$sappId};

  my @ep = $sapp-&gt;getEntryPoints();

  foreach my $node (@ep) {
    my $epNode = XmlNode-&gt;new('sapp-entry-point');
    $epNode-&gt;addChild(XmlNode-&gt;new('label', 'content' =&gt; $node-&gt;{'label'}));
    $epNode-&gt;addChild(XmlNode-&gt;new('description', 'content' =&gt; $node-&gt;{'description'}));
    $epNode-&gt;addChild(XmlNode-&gt;new('hidden', 'content' =&gt; $node-&gt;{'hidden'}));
    $epNode-&gt;addChild(XmlNode-&gt;new('http', 'content' =&gt; $node-&gt;{'http'}));
    $epNode-&gt;addChild(XmlNode-&gt;new('icon', 'content' =&gt; $node-&gt;{'icon'})) if defined $node-&gt;{'icon'};

    my $permissionsNode = XmlNode-&gt;new('limits-and-permissions');
    $permissionsNode-&gt;addChild(
      XmlNode-&gt;new('permission', 'attributes' =&gt; {'name' =&gt; $node-&gt;{'permission-name'} , 'class' =&gt; $node-&gt;{'permission-class'}})
    );
    $epNode-&gt;addChild($permissionsNode);
    $sapp_installed-&gt;addChild($epNode);
  }
}

sub setDomainSappBackupArchiveContent {
  my ( $self, $domainId, $sappId, $path, $include, $webspaceId ) = @_;
  my $sapp_installed = $self-&gt;{sappNodes}-&gt;{$sappId};
  my $cid = $self-&gt;{content_transport}-&gt;addPhostingContent( 'sapp-apsc', $domainId, $webspaceId,
    "sapp-apsc." . $sappId,
    "directory"    =&gt; $path,
    "include"      =&gt; [$include]
  );
  $sapp_installed-&gt;getChild( 'content', 1, 1 )-&gt;addChild( $cid ) if $cid;
}

sub setSubDomainSappBackupArchiveContent {
  my ( $self, $subdomainId, $sappId, $path, $include, $webspaceId ) = @_;

  my $sapp_installed = $self-&gt;{sappNodes}-&gt;{$sappId};

  my $cid = $self-&gt;{content_transport}-&gt;addSubDomainPhostingContent( 'sapp-apsc', $subdomainId, $webspaceId,
    "sapp-apsc." . $sappId,
    "directory"    =&gt; $path,
    "include"      =&gt; [$include]
  );
  $sapp_installed-&gt;getChild( 'content', 1, 1 )-&gt;addChild( $cid ) if $cid;
}


sub addDomainSappDatabase {
  my ( $self, $dbId, $dbServerId, $domainId, $sappId, $dbName, $dbType, $optionalPtr, $dbServerPtr, $dbUsersPtr, $contentDescriptionPtr, $skipContent ) = @_;

  $self-&gt;regDatabaseObjectBackupPath( $self-&gt;getDomainsBackupPath( $domainId ), $dbId, $dbName, $dbServerId );
  my $parent = $self-&gt;{sappNodes}-&gt;{$sappId};

  my $domain = $self-&gt;getCashedDomainNode($domainId);

  my $node = $self-&gt;makeDatabaseNode( $dbId, $dbName, $dbType, 'domain', $domainId, $optionalPtr,
                                      $dbServerPtr, $dbUsersPtr, $contentDescriptionPtr, $skipContent );
  my $domainGuid = $domain-&gt;getAttribute('guid');
  $node-&gt;setAttribute( 'guid', $self-&gt;getDatabaseGuid( $domainGuid, $dbId ) ) if $domainGuid;
  $node-&gt;setAttribute( 'owner-guid', $domainGuid ) if $domainGuid;
  $node-&gt;setAttribute( 'aps-registry-id', $optionalPtr-&gt;{'aps-registry-id'}) if $optionalPtr-&gt;{'aps-registry-id'};

  $parent-&gt;addChild($node);
}

sub addSubDomainSappDatabase {
  my ( $self, $dbId, $dbServerId, $subdomainId, $sappId, $dbName, $dbType, $optionalPtr, $dbServerPtr, $dbUsersPtr, $contentDescriptionPtr, $skipContent ) = @_;

  $self-&gt;regDatabaseObjectBackupPath( $self-&gt;getSubdomainsBackupPath( $subdomainId ), $dbId, $dbName, $dbServerId );
  my $subdomain = $self-&gt;{subDomainNodes}-&gt;{$subdomainId};

  my $parent = $self-&gt;{sappNodes}-&gt;{$sappId};

  my $node = $self-&gt;makeDatabaseNode( $dbId, $dbName, $dbType, 'subdomain', $subdomainId, $optionalPtr,
                                      $dbServerPtr, $dbUsersPtr, $contentDescriptionPtr, $skipContent );
  my $subDomainGuid = $subdomain-&gt;getAttribute('guid');
  $node-&gt;setAttribute( 'guid', $self-&gt;getDatabaseGuid( $subDomainGuid, $dbId ) ) if $subDomainGuid;
  $node-&gt;setAttribute( 'owner-guid', $subDomainGuid ) if $subDomainGuid;
  $node-&gt;setAttribute( 'aps-registry-id', $optionalPtr-&gt;{'aps-registry-id'}) if $optionalPtr-&gt;{'aps-registry-id'};

  $parent-&gt;addChild($node);
}

sub addDomainSappCustomButton {
    my $self = shift;
    $self-&gt;addSappCustomButton( 'domains', @_ );
}

sub addSubDomainSappCustomButton {
    my $self = shift;
    $self-&gt;addSappCustomButton( 'subdom', @_ );
}

sub addSappCustomButton {
    my ( $self, $parentType, $parentid, $sappId, $id, $optionsPtr, $customButtonsDir, $icon ) = @_;

    my $parent = $self-&gt;{sappNodes}-&gt;{$sappId};
    if ( !defined($parent) ) {
      Logging::warning('Unable to dump site applications custom buttons settings, because of dump XML structure is not full', 'PackerStructure');
      return;
    }

    my $node = $self-&gt;makeCustomButtonNode( $parentType, $parentid, $id, $optionsPtr, $customButtonsDir, $icon );

    $parent-&gt;addChild($node);
}

sub setSappApscNode {
  my ( $self, $sappId, $content) = @_;

  my $parent = $self-&gt;{sappNodes}-&gt;{$sappId};

  my $sappApscNode = XmlNode-&gt;new('sapp-apsc', 'content' =&gt; $self-&gt;{base64}-&gt;{'ENCODE'}-&gt;($content));

  $parent-&gt;addChild($sappApscNode);
}
####### End Siteapps functions #######

sub insertLimitNode {
    my ( $self, $node, $name, $value ) = @_;
    my $limits = $node-&gt;getChild( 'limits-and-permissions', 1 );
    $limits-&gt;addChild( XmlNode-&gt;new( "limit",
        "attributes" =&gt; { "name" =&gt; $name },
        "content"    =&gt; $value ) );
}

sub makePermissionNode {
  my ($self, $parent, $name, $allowed) = @_;

  #[Bug 111477] Value "-1" for attribute allowed of permission is not among the enumerated set
  if ($allowed =~ /-1/) {
   	$allowed = 'false';
  }
  $parent-&gt;addChild(  XmlNode-&gt;new('permission', 'attributes' =&gt; { 'name' =&gt; $name, 'value' =&gt; $allowed}) );
}

###### Backup content structure ######

sub getPhostingGuid{
   my ( $self, $ownerguid, $id ) = @_;
   return "$ownerguid\_ph_$id";
}

sub getDatabaseGuid{
   my ( $self, $ownerguid, $id ) = @_;
   return "$ownerguid\_db_$id";
}

sub getSubdomainGuid{
   my ( $self, $ownerguid, $id ) = @_;
   return "$ownerguid\_sb_$id";
}

sub getMailnameGuid{
   my ( $self, $ownerguid, $id ) = @_;
   return "$ownerguid\_mn_$id";
}

sub regObjectBackupPath{
 my( $self, $basePath, $group, $key, $objectId, $parentId ) = @_;
 $basePath .= '/' if $basePath;
 my $path = "$basePath$group";
 $path = $basePath if $group eq 'admin';
 $self-&gt;{backupPath}-&gt;{"$group\_$key"} = $path;
 $self-&gt;{objectId}-&gt;{"$group\_$key"} = $objectId;
 $self-&gt;{parentId}-&gt;{"$group\_$key"} = $parentId;
 return $self-&gt;getBackupPath( $group, $key, undef, 0 );
}

sub regAdminObjectBackupPath{
 my( $self, $basePath ) = @_;
 return $self-&gt;regObjectBackupPath( $basePath, 'admin', 'admin', ''  );
}

sub regResellersObjectBackupPath{
 my( $self, $basePath, $key, $resellerLogin ) = @_;
 return $self-&gt;regObjectBackupPath( $basePath, 'resellers', $key, $self-&gt;{fnamecreator}-&gt;normalize_short_string( $resellerLogin, $key ) );
}

sub regClientObjectBackupPath{
 my( $self, $basePath, $key, $clientLogin ) = @_;
 return $self-&gt;regObjectBackupPath( $basePath, 'clients', $key, $self-&gt;{fnamecreator}-&gt;normalize_short_string( $clientLogin, $key ) );
}

sub regDomainObjectBackupPath{
 my( $self, $basePath, $key, $domainAscName ) = @_;
 return $self-&gt;regObjectBackupPath( $basePath, 'domains', $key, $self-&gt;{fnamecreator}-&gt;normalize_long_string( $domainAscName, $key ) );
}

sub regSiteObjectBackupPath{
 my( $self, $basePath, $key, $siteName ) = @_;
 return $self-&gt;regObjectBackupPath( $basePath, 'sites', $key, $self-&gt;{fnamecreator}-&gt;normalize_long_string( $siteName, $key ) );
}

sub regMailnameObjectBackupPath{
 my( $self, $basePath, $key, $mailName, $domainId ) = @_;
 return $self-&gt;regObjectBackupPath( $basePath, 'mailnames', $key, $self-&gt;{fnamecreator}-&gt;normalize_short_string( $mailName, $key ), $domainId );
}

sub regDatabaseObjectBackupPath{
 my( $self, $basePath, $key, $databaseName, $dbServerId ) = @_;
 return $self-&gt;regObjectBackupPath( $basePath, 'databases', $key, $self-&gt;{fnamecreator}-&gt;normalize_short_string( "$databaseName\_$dbServerId", $key ) );
}

sub regSubdomainObjectBackupPath{
 my( $self, $basePath, $key, $subdomainName, $domainId ) = @_;
 return $self-&gt;regObjectBackupPath( $basePath, 'subdomains', $key, $self-&gt;{fnamecreator}-&gt;normalize_short_string( $subdomainName, $key ), $domainId );
}

sub regPhostingObjectBackupPath{
 my( $self, $basePath, $key ) = @_;
 return $self-&gt;regObjectBackupPath( $basePath, 'phosting', $key, '' );
}

sub getObjectId{
 my( $self, $group, $key ) = @_;
 $key = "$group\_$key";
 return 'phosting' if $group eq 'phosting';
 return 'admin' if $group eq 'admin';
 return $self-&gt;{objectId}-&gt;{$key};
}

sub getParentId{
 my( $self, $group, $key ) = @_;
 $key = "$group\_$key";
 return $self-&gt;{parentId}-&gt;{$key}  if exists $self-&gt;{parentId} &amp;&amp; exists $self-&gt;{parentId}-&gt;{$key};
 return;
}

sub getPhostingParentId{
 my( $self, $key ) = @_;
 return $key;
}

sub getSubdomainParentId{
 my( $self, $key ) = @_;
 return $self-&gt;getParentId( "subdomains", $key );
}

sub getMailNameParentId{
 my( $self, $key ) = @_;
 return $self-&gt;getParentId( "mailnames", $key );
}

sub getBackupPath{
 my( $self, $group, $key, $fileName, $onlyFileName ) = @_;
 $key = "$group\_$key";
 my $res = '';
 if( not $onlyFileName ) {
     $res .=  $self-&gt;{backupPath}-&gt;{$key};
     $res .= '/' . $self-&gt;{objectId}-&gt;{$key} if $group ne 'phosting' and $group ne 'admin';
 }
 $res = $self-&gt;{fnamecreator}-&gt;getFileName( $res, $self-&gt;{backupname}, $self-&gt;{objectId}-&gt;{$key}, $fileName ) if defined $fileName;
 return $res;
}

sub getAdminBackupPath{
 my( $self, $fileName, $onlyFileName ) = @_;
 return $self-&gt;getBackupPath( 'admin', 'admin', $fileName, $onlyFileName );
}

sub getResellersBackupPath{
 my( $self, $key, $fileName, $onlyFileName ) = @_;
 return $self-&gt;getBackupPath( 'resellers', $key, $fileName, $onlyFileName );
}

sub getClientsBackupPath{
 my $self = shift;
 my $key = shift;
 return $self-&gt;getBackupPath( 'clients', $key, @_ ) if exists $self-&gt;{objectId}-&gt;{"clients_$key"};
 return $self-&gt;getResellersBackupPath( $key, @_ );
}

sub getDomainsBackupPath{
 my( $self, $key, $fileName, $onlyFileName ) = @_;
 if ( defined $self-&gt;{domainNodes}-&gt;{$key} ) {
    return $self-&gt;getBackupPath( 'domains', $key, $fileName, $onlyFileName );
 }
 return $self-&gt;getBackupPath( 'sites', $key, $fileName, $onlyFileName );
}

sub getSitesBackupPath{
 my $self = shift;
 return $self-&gt;getBackupPath( 'sites', @_ );
}

sub getPhostingBackupPath{
 my $self = shift;
 return $self-&gt;getBackupPath( 'phosting', @_ );
}

sub getDatabasesBackupPath{
 my $self = shift;
 return $self-&gt;getBackupPath( 'databases', @_ );
}

sub getMailnamesBackupPath{
 my $self = shift;
 return $self-&gt;getBackupPath( 'mailnames', @_ );
}

sub getSubdomainsBackupPath{
 my $self = shift;
 return $self-&gt;getBackupPath( 'subdomains', @_ );
}

sub getAdminObjectId{
 my( $self ) = @_;
 return $self-&gt;getObjectId( 'admin', 'admin' );
}

sub getResellerObjectId{
 my( $self, $key ) = @_;
 return $self-&gt;getObjectId( 'resellers', $key );
}

sub getClientObjectId{
 my( $self, $key ) = @_;
 return $self-&gt;getResellerObjectId( $key ) if exists $self-&gt;{objectId}-&gt;{"resellers_$key"};
 return $self-&gt;getObjectId( 'clients', $key );
}

sub getDomainObjectId{
 my( $self, $key ) = @_;
 return $self-&gt;getObjectId( 'domains', $key );
}

sub getPhostingObjectId{
 my( $self, $key ) = @_;
 return $self-&gt;getObjectId( 'phosting', $key );
}

sub getDatabaseObjectId{
 my( $self, $key ) = @_;
 return $self-&gt;getObjectId( 'databases', $key );
}

sub getMailnameObjectId{
 my( $self, $key ) = @_;
 return $self-&gt;getObjectId( 'mailnames', $key );
}

sub getSubdomainObjectId{
 my( $self, $key ) = @_;
 return $self-&gt;getObjectId( 'subdomains', $key );
}
###### End Backup content structure ######

sub addTemplateItem {
    my ( $self, $node, $name, $value ) = @_;
    $node-&gt;addChild( XmlNode-&gt;new( "template-item",
        "attributes" =&gt; { "name" =&gt; $name },
        "content"    =&gt; $value ) );
}

sub makeTemplatePlanItem {
  my ( $self, $name, $value ) = @_;

  my $templatePlanItemNode = XmlNode-&gt;new( "template-plan-item",
                                           "attributes" =&gt; { "name" =&gt; $name },
                                           "content"    =&gt; $value );
  return $templatePlanItemNode;
}

sub addTemplatePlanItem {
  my ( $self, $node, $name, $value ) = @_;

  my $templatePlanItemNode = $self-&gt;makeTemplatePlanItem( $name, $value );
  $node-&gt;addChild( $templatePlanItemNode ) if defined $templatePlanItemNode;
}

sub makeLogrotationNode {
  my ( $self, $parent, $logRotationPtr ) = @_;

  my %logRotation = %{$logRotationPtr};

  my $item = XmlNode-&gt;new( 'logrotation', 'attributes' =&gt; {
        'max-number-of-logfiles' =&gt; $logRotation{'max_number_of_logfiles'},
        'compress'               =&gt; $logRotation{'compress_enable'}
    } );

  $item-&gt;setAttribute( 'email', $logRotation{'email'} ) unless $logRotation{'email'} eq '';
  $item-&gt;setAttribute( 'enabled', $logRotation{'turned_on'} );

  my $rottype;
  if ( $logRotation{'period_type'} eq 'by_time' ) {
    $rottype = XmlNode-&gt;new( 'logrotation-period',
                             'attributes' =&gt; { 'period' =&gt; $logRotation{'period'} } );
  }
  else {
    $rottype = XmlNode-&gt;new( 'logrotation-maxsize',
                             'content' =&gt; $logRotation{'period'} );
  }
  $item-&gt;addChild($rottype);
  $parent-&gt;addChild($item);
}

sub makeDatabaseNode {
    my ( $self, $dbId, $dbName, $dbType, $parent, $parentId, $optionalPtr, $dbServerPtr, $dbUsersPtr, $contentDescriptionPtr, $skipContent ) = @_;

    my %optional = %{$optionalPtr};
    my %dbServer = %{$dbServerPtr};
    my @dbUsers = @{$dbUsersPtr};
    my %contentDescription = %{$contentDescriptionPtr};

    my $root = XmlNode-&gt;new( 'database', 'attributes' =&gt; {
        'name' =&gt; $dbName,
        'type' =&gt; $dbType,
        'id' =&gt; $dbId
        } );

    $root-&gt;setAttribute( 'version', $optional{'version'} )
      if $optional{'version'};
    $root-&gt;setAttribute( 'charset', $optional{'charset'} )
      if $optional{'charset'};
    $root-&gt;setAttribute( 'version', $optional{'version'} )
      if $optional{'version'};
    $root-&gt;setAttribute( 'db-existent', $optional{'db-existent'} )
      if $optional{'db-existent'};
    $root-&gt;setAttribute( 'prefix', $optional{'prefix'} )
      if $optional{'prefix'};
    $root-&gt;setAttribute( 'collation', $optional{'collation'} )
      if $optional{'collation'};
    $root-&gt;setAttribute( 'external-id', $optional{'external_id'} )
      if defined $optional{'external_id'} and $optional{'external_id'} ne '';
    $root-&gt;setAttribute( 'custom-host', $optional{'custom-host'} )
      if (defined($optional{'custom-host'}));

    if (%dbServer) {
      my $dbServerNode = XmlNode-&gt;new('db-server');
      $dbServerNode-&gt;setAttribute( 'type', $dbServer{'type'} );
      $dbServerNode-&gt;addChild( XmlNode-&gt;new( 'host', 'content' =&gt; $dbServer{'host'} ) );
      $dbServerNode-&gt;addChild( XmlNode-&gt;new( 'port', 'content' =&gt; $dbServer{'port'} ) );

      $root-&gt;addChild($dbServerNode);
    }

    $self-&gt;makeDatabaseUsersNodes($root, \@dbUsers, $dbId);

    if (defined($optional{'related-sites'})) {
      $self-&gt;makeRelatedSitesNode($root, $optional{'related-sites'});
    }

    if (%contentDescription and !$skipContent) {
      my $cid;
      if( $parent eq 'subdomain' ) {
        $cid = $self-&gt;{content_transport}-&gt;addSubdomainDbContent( 'sqldump', $parentId, $dbId, %contentDescription );
      }
      else{
        $cid = $self-&gt;{content_transport}-&gt;addDbContent( 'sqldump', $dbId, %contentDescription );
      }
      $root-&gt;getChild( 'content', 1, 1 )-&gt;addChild( $cid ) if $cid;
      $self-&gt;{stat}{dbSizeDumped} += $self-&gt;_getContentSizeFromCidNode($cid) if $cid;
    }

    $self-&gt;{databaseNodes}-&gt;{$dbId} = $root;
    return $root;
}

sub makeDbUsersToAnyDatabasesNode {
  my ( $self, $domainId, $dbUsersPtr ) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my $rootNode = $root-&gt;getChild( 'databases', 1 );

  my $globalDbUsersNode = XmlNode-&gt;new('dbusers');

  $self-&gt;makeDatabaseUsersNodes($globalDbUsersNode, $dbUsersPtr);

  $rootNode-&gt;addChild($globalDbUsersNode);
}

sub makeDatabaseUsersNodes {
    my ( $self, $parentNode, $dbUsersPtr, $dbId ) = @_;
    $dbId ||= 0;

    my @dbUsers = @{$dbUsersPtr};

    my $item;
    foreach my $user (@dbUsers) {
      my $dbUserRoot = XmlNode-&gt;new( 'dbuser',
        'attributes' =&gt; { 'name' =&gt; $user-&gt;{'login'}, 'id' =&gt; $user-&gt;{'id'} } );
 
      $dbUserRoot-&gt;setAttribute( 'default', ( defined( $user-&gt;{'default'} ) ) ? 'true' : 'false' );

      $dbUserRoot-&gt;setAttribute('aps-registry-id', $user-&gt;{'aps-registry-id'}) if $user-&gt;{'aps-registry-id'};
      $dbUserRoot-&gt;setAttribute('db-user-existent', $user-&gt;{'db-user-existent'}) if $user-&gt;{'db-user-existent'};

      $dbUserRoot-&gt;setAttribute('external-id', $user-&gt;{'external_id'}) if defined $user-&gt;{'external_id'} and $user-&gt;{'external_id'} ne '';

      $item = CommonPacker::makePasswordNode( $user-&gt;{'password'}, CommonPacker::normalizePasswordType( $user-&gt;{'type'} ) );

      $dbUserRoot-&gt;addChild($item);

      if ($user-&gt;{'host'}) {
        my %dbServer;
        $dbServer{'host'} = $user-&gt;{'host'};
        $dbServer{'port'} = $user-&gt;{'port'};
        $dbServer{'type'} = $user-&gt;{'dbservertype'};

        my $dbServerNode = $self-&gt;makeDbServerNodeWithoutCredentials(\%dbServer);
        $dbUserRoot-&gt;addChild($dbServerNode);
      }
      my $databaseUserRemoteAccessRulesNode = $self-&gt;makeDatabaseUserRemoteAccessRulesNode($user, $dbId);
      if ($databaseUserRemoteAccessRulesNode) {
          $dbUserRoot-&gt;addChild($databaseUserRemoteAccessRulesNode);
      }

      if ( exists $user-&gt;{'acl'} ) {
        my $aclNode = XmlNode-&gt;new( 'acl' );
        foreach my $acl ( @{$user-&gt;{'acl'}} ) {
          $aclNode-&gt;addChild( XmlNode-&gt;new( 'allowed-host', 'content' =&gt; $acl ) );
        }
        $dbUserRoot-&gt;addChild( $aclNode );
      }

      if (exists($user-&gt;{'privileges'})) {
        my $privilegesNode = XmlNode-&gt;new('privileges');
        foreach my $privilege (@{$user-&gt;{'privileges'}}) {
          $privilegesNode-&gt;addChild(XmlNode-&gt;new('privilege', 'attributes' =&gt;  $privilege));
        }
        $dbUserRoot-&gt;addChild($privilegesNode);
      }

      $parentNode-&gt;addChild($dbUserRoot);
    }
}

sub makeRelatedSitesNode {
    my ($self, $parentNode, $relatedSites) = @_;

    my $relatedSitesNode = XmlNode-&gt;new('related-sites');
    foreach my $relatedSiteName (@{$relatedSites}) {
      my $relatedSiteNode = XmlNode-&gt;new('related-site');
      $relatedSiteNode-&gt;setAttribute('name', $relatedSiteName);
      $relatedSitesNode-&gt;addChild($relatedSiteNode);
    }
    $parentNode-&gt;addChild($relatedSitesNode);
}

sub makeAutoresponderNode {
    my ( $self, $enabled, $autoPtr, $mailName ) = @_;

    my %auto = %{$autoPtr};

    my $root = XmlNode-&gt;new('autoresponder');

    my $value = $self-&gt;{base64}-&gt;{'ENCODE'}-&gt;( $auto{'text'} );

    my $item = XmlNode-&gt;new( 'text', 'content' =&gt; $value );
    if ( exists $auto{'charset'} &amp;&amp; $auto{'charset'} ne '' ) {
      $item-&gt;setAttribute( 'charset', $auto{'charset'} );
    }
    $root-&gt;addChild($item);

    if ( exists $auto{'content_type'} &amp;&amp; $auto{'content_type'} ) {
      $root-&gt;setAttribute( 'content-type', $auto{'content_type'} );
    }

    $root-&gt;setAttribute( 'status', ($enabled eq 'true' &amp;&amp; $auto{'resp_on'} eq 'true') ? 'on' : 'off' );

    if ( $auto{'subject'} ) {
      $value = $self-&gt;{base64}-&gt;{'ENCODE'}-&gt;( $auto{'subject'} );
      chomp $value;
      $root-&gt;setAttribute( 'subject', $value );
    }

    #
    # forward
    #
    if ( $auto{'redirect'} ) {
      $root-&gt;setAttribute( 'redirect', $auto{'redirect'} );
    }

    #
    # end forward
    #

    if (exists($auto{'ans_freq'})) {
      $root-&gt;addChild( XmlNode-&gt;new( 'autoresponder-limit',
          'content'    =&gt; $auto{'ans_freq'},
          'attributes' =&gt; { 'name' =&gt; 'ans-freq' } ) );
    }
    if (exists($auto{'endDate'})) {
      $root-&gt;addChild( XmlNode-&gt;new( 'autoresponder-limit',
          'content'    =&gt; $auto{'endDate'},
          'attributes' =&gt; { 'name' =&gt; 'end-date' } ) );
    }

    my @attach = @{$auto{'attach'}};
    if ( @attach ) {
      foreach my $file (@attach) {
        $root-&gt;addChild( XmlNode-&gt;new( 'attach', 'attributes' =&gt; { 'file' =&gt; $file } ) );
      }
    }

    return $root;
}

sub parseCustomButtonOptions {
    my ( $node, $options ) = @_;

    #CUSTOM_BUTTON_PUBLIC
    $node-&gt;setAttribute( 'visible-to-sublogins', $options &amp; 128 ? 'true' : 'false' );

    #CUSTOM_BUTTON_INTERNAL
    $node-&gt;setAttribute( 'open-in-same-frame', $options &amp; 256 ? 'true' : 'false' );

    $node-&gt;setAttribute( 'no-frame', $options &amp; 64 ? 'true' : 'false' );

    my %options = (
      "domain-id"           =&gt; 1,       #CUSTOM_BUTTON_DOM_ID
      "domain-name"         =&gt; 32,      #CUSTOM_BUTTON_DOM_NAME
      "ftp-login"           =&gt; 512,     #CUSTOM_BUTTON_FTP_USER
      "ftp-password"        =&gt; 1024,    #CUSTOM_BUTTON_FTP_PASS
      "client-id"           =&gt; 2,       #CUSTOM_BUTTON_CL_ID
      "client-company-name" =&gt; 4,       #CUSTOM_BUTTON_CNAME
      "client-contact-name" =&gt; 8,       #CUSTOM_BUTTON_PNAME
      "client-email"        =&gt; 16,      #CUSTOM_BUTTON_EMAIL
      );

    while ( my ( $optname, $optmask ) = each %options ) {
      if ( $options &amp; $optmask ) {
        $node-&gt;addChild(
          XmlNode-&gt;new( "url-option", "attributes" =&gt; { "name" =&gt; $optname } )
        );
      }
    }
}

sub addAdminContentProxy{
    my $self = shift;
    $self-&gt;{content_transport}-&gt;addAdminContent(@_);
}

sub addClientContentProxy{
    my $self = shift;
    $self-&gt;{content_transport}-&gt;addClientContent(@_);
}

sub addDomainContentProxy{
    my $self = shift;
    $self-&gt;{content_transport}-&gt;addDomainContent(@_);
}

sub addMailnameContentProxy{
    my $self = shift;
    $self-&gt;{content_transport}-&gt;addMailnameContent(@_);
}

sub addCustomButtonNode {
  my ( $self, $optionsPtr) = @_;

  my %options = %{$optionsPtr};

  my $node = XmlNode-&gt;new('custom-button');

  my %attributes = (
    'url'      =&gt; 'url',
    'text'     =&gt; 'text',
    'sort_key' =&gt; 'sort-priority',
    'place'    =&gt; 'interface-place',
    'conhelp'  =&gt; 'conhelp' );

  foreach my $key (keys %attributes) {
    $node-&gt;setAttribute( $attributes{$key}, $options{$key} ) if defined $options{$key};
  }

  return $node;

}

sub makeCustomButtonNode65 {
  my ( $self, $optionsPtr ) = @_;
  my $node = $self-&gt;addCustomButtonNode($optionsPtr);

  ## 128 == CUSTOM_BUTTON_PUBLIC
  parseCustomButtonOptions( $node, $optionsPtr-&gt;{'options'} | 128 );

  return $node;

}

sub makeCustomButtonNode {
  my ( $self, $parentType, $parentId, $id, $optionsPtr, $customButtonsDir, $icon ) = @_;

  my $node = $self-&gt;addCustomButtonNode($optionsPtr);
  my %options = %{$optionsPtr};

  if ( -e $customButtonsDir . "/" . $icon ) {
    if ($icon) {
      my $proc;
      if( $parentType eq 'admin' ) { $proc = \&amp;addAdminContentProxy; }
      elsif( $parentType eq 'clients' ) { $proc = \&amp;addClientContentProxy; }
      elsif( $parentType eq 'domains' ) { $proc = \&amp;addDomainContentProxy; }
      elsif( $parentType eq 'mails' ) { $proc = \&amp;addMailnameContentProxy; }
      else{
        Logging::warning( "Error: makeCustomButtonNode: unsupported parent type '$parentType' ",'assert');
      }
      if( $proc ) {
        my $cid_icon =
          ( AgentConfig::tarVersionMoreThan15() )
          ? $self-&gt;$proc(
          'icon',
          $parentId,
          $icon . "." . $id,
          "directory" =&gt; $customButtonsDir,
          "add_file"  =&gt; $icon
          )
          : $self-&gt;$proc(
          'icon',
          $parentId,
          $icon . "." . $id,
          "directory" =&gt; $customButtonsDir,
          "include"   =&gt; [$icon]
          );

        $node-&gt;getChild( 'content', 1, 1 )-&gt;addChild( $cid_icon ) if $cid_icon;
      }
    }
  }
  parseCustomButtonOptions( $node, $options{'options'} );

  # exists $options{'plan_item_name'}   &lt;=&gt;   (PleskVersion::atLeast( 10, 1, 0))
  if ( defined $options{'plan_item_name'} &amp;&amp; ( '' ne $options{'plan_item_name'} ) ) {
    my $templatePlanItemNode = $self-&gt;makeTemplatePlanItem( $options{'plan_item_name'}, '' );
    $node-&gt;addChild( $templatePlanItemNode );
  }

  return $node;
}

sub makeDnsZoneParam {
  my ( $self, $name, $db_unit, $db_value ) = @_;

  my $dnsZoneParam =
    XmlNode-&gt;new( 'dns-zone-param',
    'attributes' =&gt; { 'name' =&gt; $name, 'value' =&gt; $db_value } );

  my %units = (
    'second'  =&gt; 1,
    'minutes' =&gt; 60,
    'hours'   =&gt; 3600,
    'days'    =&gt; 86400,
    'weeks'   =&gt; 604800
  );
  my $string_unit;

  foreach my $quant ( keys %units ) {
    if ( $units{$quant} == $db_unit ) {
      $string_unit = $quant;
      last;
    }
  }
  $dnsZoneParam-&gt;setAttribute( 'unit', $string_unit );

  return $dnsZoneParam;
}

sub makeDnsZone {
  my ( $self, $parent, $paramsPtr, $recordsPtr, $syncWithParent ) = @_;

  my %params = %{$paramsPtr};
  my @records = @{$recordsPtr};

  my $email;
  if ( defined($params{'email'}) and (length( $params{'email'} ) != 0) ) {
    $email = $params{'email'};
  }
  else {

    # should assume some default email or something...
    $email = 'root@localhost.localdomain';
  }

  my $dnsZone = XmlNode-&gt;new( 'dns-zone',
    'attributes' =&gt; { 'email' =&gt; $email, 'type' =&gt; $params{'type'} },
    'children' =&gt; [ Status::make( $params{'status'} ) ] );

  if ( exists $params{'serial_format'} ){
     $dnsZone-&gt;setAttribute( 'serial-format', $params{'serial_format'} );
  }
  if ( defined $syncWithParent ) {
    $dnsZone-&gt;setAttribute( 'sync-with-parent', $syncWithParent );
  }

  $dnsZone-&gt;setAttribute('external-id', $params{'external_id'}) if defined $params{'external_id'} and $params{'external_id'} ne '';

  foreach my $zoneParam ( 'ttl', 'refresh', 'retry', 'expire', 'minimum' ) {
    $dnsZone-&gt;addChild(
      $self-&gt;makeDnsZoneParam(
        $zoneParam, $params{ $zoneParam . '_unit' },
        $params{$zoneParam}
      )
    );
  }

  # dns records
  for my $hash (@records) {
    my $dnsrec = $self-&gt;makeDnsRecord( $hash );
    if ($dnsrec) {
      $dnsZone-&gt;addChild($dnsrec);
    }
  }

  $parent-&gt;addChild($dnsZone);
}

sub makeDnsRecord {
  my ( $self, $hashPtr ) = @_;

  unless (ref($hashPtr) =~ /HASH/)
  {
    Logging::warning('Error: makeDnsRecord: hashPtr is not hash ptr', 'assert');
    return;
  }
  my %hash = %{$hashPtr};

  return unless $hash{'type'} =~ /^A|AAAA|NS|MX|CNAME|PTR|TXT|master|SRV|AXFR|DS$/;
  return if $hash{'displayHost'} &amp;&amp; $hash{'displayHost'} =~ /.*_domainkey.*/;

  my $host =
    defined $hash{'displayHost'}
    ? $hash{'displayHost'}
    : $hash{'host'};
  my $val =
    defined $hash{'displayVal'}
    ? $hash{'displayVal'}
    : $hash{'val'};

  if ( $hash{'type'} eq 'SRV' ) {
    $host =~ s/\.$//;
    $val  =~ s/\.$//;
  }

  my ($item) =
    XmlNode-&gt;new( 'dnsrec',
    'attributes' =&gt; { 'type' =&gt; $hash{'type'}, 'src' =&gt; $host } );
  $item-&gt;setAttribute( 'dst', $val ) if ($val);
  $item-&gt;setAttribute( 'opt', $hash{'opt'} ) if ( defined $hash{'opt'} );
  $item-&gt;setAttribute( 'status', $hash{'status'} ) if (defined $hash{'status'});
  $item-&gt;setAttribute('external-id', $hash{'external_id'}) if defined $hash{'external_id'} and $hash{'external_id'} ne '';

  return $item;
}

#
# Creates node representing pre-8.0 DNS master record
#

sub makeOldMasterRec {
  my ($ipAddress) = @_;

  return XmlNode-&gt;new(
    "dnsrec",
    "attributes" =&gt; {
      "src"  =&gt; $ipAddress,
      "type" =&gt; "master"
    }
  );
}

sub addUrlDecodedTextNode {
  my ( $parent, $name, $value ) = @_;

  $parent-&gt;addChild( XmlNode-&gt;new( $name, "content" =&gt; HelpFuncs::urlDecode($value) ) )
    if $value;
}

sub makeSysUser {
  my ( $self, $sysuserPtr ) = @_;

  my %sysuser = %{$sysuserPtr};

  #
  # attributes
  #

  my $root =
    XmlNode-&gt;new( 'sysuser',
    'attributes' =&gt; { 'name' =&gt; lc( $sysuser{'login'} ) } );
  $root-&gt;setAttribute( 'shell', $sysuser{'shell'} ) if $sysuser{'shell'} and $sysuser{'shell'} ne '/bin/false';

  my $quota;
  if ( $sysuser{'quota'} ) {
    $quota = $sysuser{'quota'};
    $root-&gt;setAttribute( 'quota', $quota ) if $quota;
  }

  if ( $sysuser{'home'} ) {
    my $home = $sysuser{'home'};
    if (exists $sysuser{'relative_path'}) {
      if (substr($home,0, length($sysuser{'relative_path'})) eq $sysuser{'relative_path'} ) {
        $home = substr($home, length($sysuser{'relative_path'}));
      }
    }
    $root-&gt;setAttribute( 'home', $home) if $home;
  }

  #
  # end attributes
  #

  $root-&gt;addChild( CommonPacker::makePasswordNode( $sysuser{'passwd'}, $sysuser{'passwdType'} ) );

  if (defined($sysuser{'scheduled-tasks'})) {
    $self-&gt;addEmbeddedInfo($root, 'scheduled-tasks', $sysuser{'scheduled-tasks'});
  } elsif ( $sysuser{'cron'} ) {
    my $cronNode = XmlNode-&gt;new( 'cron', 'content' =&gt; $sysuser{'cron'} );
    if ( $sysuser{'cron-encoding'} ) {
      $cronNode-&gt;setAttribute( 'encoding', $sysuser{'cron-encoding'} );
    }
    $root-&gt;addChild( $cronNode );
  }

  return $root;
}

sub makeSappNode {

  my ( $self, $sappId, $sapp, $licenseType ) = @_;

  my $name = $sapp-&gt;getName();
  my $version = $sapp-&gt;getVersion();
  my $release = $sapp-&gt;getRelease();
  my $description = $sapp-&gt;getDescription();
  my $isCommercial = $sapp-&gt;isCommercial();
  my $isIntegrated = $sapp-&gt;isIntegrated();
  my $prefix = $sapp-&gt;getInstallPrefix();
  my $isSsl = $sapp-&gt;isSsl();
  my $packageId = $sapp-&gt;getSappPackageId();

  my $sapp_installed = XmlNode-&gt;new('sapp-installed');

  #-----------------------------------------------------------------
  # sapp-spec
  #-----------------------------------------------------------------
  my $sapp_spec = XmlNode-&gt;new('sapp-spec');
  if ( $packageId ) {
    $sapp_spec-&gt;addChild(
      XmlNode-&gt;new( 'sapp-package-id', 'content' =&gt; $packageId ) );
  }

  $sapp_spec-&gt;addChild( XmlNode-&gt;new( 'sapp-name', 'content' =&gt; $name ) );
  if ( $version ) {
    $sapp_spec-&gt;addChild(
      XmlNode-&gt;new( 'sapp-version', 'content' =&gt; $version ) );
  }
  if ( $release ) {
    $sapp_spec-&gt;addChild(
      XmlNode-&gt;new( 'sapp-release', 'content' =&gt; $release ) );
  }
  if ( $description ) {
    my $desc = $self-&gt;{base64}-&gt;{'ENCODE'}-&gt;( $description );
    $sapp_spec-&gt;addChild(
      XmlNode-&gt;new(
        'sapp-description',
        'attributes' =&gt; { 'encoding' =&gt; 'base64' },
        'content'    =&gt; $desc
      )
    );
  }
  if ( $isCommercial ) {
    $sapp_spec-&gt;addChild( XmlNode-&gt;new('sapp-commercial') );
  }
  if ( $isIntegrated ) {
    $sapp_spec-&gt;addChild( XmlNode-&gt;new('sapp-integrated') );
  }

  $sapp_installed-&gt;addChild($sapp_spec);

  if ( defined($licenseType) ) {
    $sapp_installed-&gt;addChild(
      XmlNode-&gt;new(
        'sapp-installed-license-type',
        'content' =&gt; $licenseType
      )
    );
  }

  return $sapp_installed;
}

sub makeSiteAppInstalled{
  my ( $self, $sappId, $prefix, $isSsl, $apsRegistryId ) = @_;

  my $sapp_installed = $self-&gt;{sappNodes}-&gt;{$sappId};

  # sapp-installdir
  my $sapp_installdir =
    XmlNode-&gt;new( 'sapp-installdir',
    'children' =&gt; [ XmlNode-&gt;new( 'sapp-prefix', 'content' =&gt; $prefix ) ] );
  if ( $isSsl ) {
    $sapp_installdir-&gt;addChild( XmlNode-&gt;new('sapp-ssl') );
  }
  if ($apsRegistryId) {
    $sapp_installdir-&gt;addChild( XmlNode-&gt;new( 'aps-registry-id', 'content' =&gt; $apsRegistryId ));
  }
  $sapp_installed-&gt;addChild($sapp_installdir);
}

sub setSappApsControllerInfo {
  my ( $self, $sappId, $sapp ) = @_;
  my $sapp_installed = $self-&gt;{sappNodes}-&gt;{$sappId};

  if ( $sapp-&gt;getContext() ) {
    $sapp_installed-&gt;addChild( XmlNode-&gt;new( 'context', 'attributes' =&gt; { "type" =&gt;  $sapp-&gt;getContext() } ) );
  }

  if ( $sapp-&gt;getApplicationApsRegistryId() ) {
    $sapp_installed-&gt;addChild( XmlNode-&gt;new( 'aps-registry-id', 'content' =&gt; $sapp-&gt;getApplicationApsRegistryId() ) );
  }
}

sub setSappApsLicense {
  my ( $self, $sappId, $sapp ) = @_;

  my $sapp_installed = $self-&gt;{sappNodes}-&gt;{$sappId};

  if ( $sapp-&gt;isContainLicense() ) {
    my $licenseNode = XmlNode-&gt;new('sapp-license');
    $licenseNode-&gt;addChild( XmlNode-&gt;new('aps-registry-id', 'content' =&gt; $sapp-&gt;getLicenseApsRegistryId())) if $sapp-&gt;getLicenseApsRegistryId();
    $licenseNode-&gt;addChild( XmlNode-&gt;new('license-type', 'content' =&gt; $sapp-&gt;getLicenseType()));
    $licenseNode-&gt;addChild( XmlNode-&gt;new('activation-code', 'content' =&gt; $sapp-&gt;getActivationCode()));
    $licenseNode-&gt;addChild( XmlNode-&gt;new('use-stub', 'content' =&gt; $sapp-&gt;getUseStub()));
    $sapp_installed-&gt;addChild($licenseNode);
  }
}

sub makeAnonftpPermissionNode {
  my ( $parent, $name ) = @_;

  $parent-&gt;addChild(
    XmlNode-&gt;new( 'anonftp-permission', "attributes" =&gt; { "name" =&gt; $name } ) );
}

sub makeAnonftpLimitNode {
  my ( $parent, $name, $value ) = @_;
  if ( $value != 0 ) {
    $parent-&gt;addChild(
      XmlNode-&gt;new(
        "anonftp-limit",
        "attributes" =&gt; { "name" =&gt; $name },
        "content"    =&gt; $value
      )
    );
  }
}

sub makeSystemIpNode {
  my ( $self, $parent, $ptrIp ) = @_;
  my $correctMask = HelpFuncs::blockToNum( $ptrIp-&gt;{'mask'} );
  my $md5 = PerlMD5-&gt;new();
  $md5-&gt;add(HelpFuncs::urlDecode($ptrIp-&gt;{'pvtkey'}));
  $parent-&gt;getChild( 'properties', 1 )-&gt;addChild(
    XmlNode-&gt;new(
      'system-ip',
      'attributes' =&gt; { 'certificate' =&gt; $md5-&gt;hexdigest() },
      'children'   =&gt; [
        XmlNode-&gt;new(
          'ip',
          'children' =&gt; [
            XmlNode-&gt;new( 'ip-type', 'content' =&gt; "$ptrIp-&gt;{'type'}" ),
            XmlNode-&gt;new(
              'ip-address', 'content' =&gt; $ptrIp-&gt;{'ip_address'}
            )
          ]
        ),
        XmlNode-&gt;new( 'ip-netmask',   'content' =&gt; "$correctMask" ),
        XmlNode-&gt;new( 'ip-interface', 'content' =&gt; "$ptrIp-&gt;{'iface'}" )
      ]
    )
  );
}

sub makeTemplateNode {
  my ( $self, $nodeName, $templateName, $data ) = @_;

  my ( $templateAttrs, $templatePtr, $planItemsPtr, $apsBundleFilterItemsPtr, $filterType, $phpSettingsPtr, $defaultDbServersPtr );

  $templateAttrs = $data-&gt;{'attributes'};
  $templatePtr = $data-&gt;{'data'};
  $planItemsPtr = $data-&gt;{'items'};
  $apsBundleFilterItemsPtr = $data-&gt;{'aps-filter-items'};
  $filterType = $data-&gt;{'aps-filter-type'};
  $phpSettingsPtr = $data-&gt;{'php-settings'};
  $defaultDbServersPtr = $data-&gt;{'default-db-servers'};

  my %logRotation = %{$data-&gt;{'log-rotation'}};
  my %ipPool = %{$data-&gt;{'ip-pool'}};

  my $node =
    XmlNode-&gt;new( $nodeName,
    'attributes' =&gt; { 'name' =&gt; $templateName } );

  for my $ptrRowAttrs ( @{$templateAttrs} ) {
      my ($attrName, $attrValue ) = @{$ptrRowAttrs};
      $node-&gt;setAttribute( $attrName, $attrValue );
  }

  for my $ptrRow ( @{$templatePtr} ) {
      my ( $element, $value ) = @{$ptrRow};
      $self-&gt;addTemplateItem( $node, $element, $value );
  }

  while ( my ($itemName, $itemValue) = each ( %{$planItemsPtr} ) ) {
    $self-&gt;addTemplatePlanItem( $node, $itemName, $itemValue );
  }

  if (keys %logRotation){
      $self-&gt;makeLogrotationNode( $node, \%logRotation );
  }

  if (%ipPool and scalar(keys %ipPool) &gt; 0){
	  my $ipPoolNode = XmlNode-&gt;new( 'ip_pool' );

	  for my $ip ( keys %ipPool ) {
        $ipPoolNode-&gt;addChild(
	      $self-&gt;makeIpNode($ip, $ipPool{$ip} )
	    );
	  }

      $node-&gt;addChild($ipPoolNode);
  }

  if (@{$apsBundleFilterItemsPtr}) {
    $self-&gt;makeApsBundleFilterNode(undef, undef, $filterType, $apsBundleFilterItemsPtr, $node);
  }

  if (defined $phpSettingsPtr and $nodeName ne 'reseller-template') {
    $node-&gt;addChild($self-&gt;makePhpSettingsNode($phpSettingsPtr));
  }

  if (defined $defaultDbServersPtr and $nodeName eq 'domain-template') {
    $node-&gt;addChild($self-&gt;makeDefaultDbServersNode($defaultDbServersPtr));
  }

  return $node;
}

sub makeDomainDefaultDbServersNode {
  my ($self, $domainId, $defaultDbServersPtr) = @_;

  my $parent = $self-&gt;getCashedDomainNode($domainId);

  $parent-&gt;getChild( 'preferences', 1 )-&gt;addChild($self-&gt;makeDefaultDbServersNode($defaultDbServersPtr));

}

sub makeDefaultDbServersNode {
  my ($self, $defaultDbServersPtr) = @_;

  my $defaulDbServersNode = XmlNode-&gt;new('default-db-servers');

  foreach my $dbServer (@{$defaultDbServersPtr}) {
    $defaulDbServersNode-&gt;addChild($self-&gt;makeDbServerNodeWithoutCredentials($dbServer));
  }

  return $defaulDbServersNode;
}

sub setDomainPhpSettingsNode {
  my ($self, $domainId, $phpSettingsPtr) = @_;

  my $parent = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $parent;

  if (defined $phpSettingsPtr) {
    $parent-&gt;addChild($self-&gt;makePhpSettingsNode($phpSettingsPtr));
  }
}

sub makePhpSettingsNode {
  my ($self, $phpSettingsPtr) = @_;

  return unless (defined $phpSettingsPtr and (scalar keys %{$phpSettingsPtr} != 0));

  my $node = XmlNode-&gt;new('php-settings');

  if (exists $phpSettingsPtr-&gt;{'notice'}) {
    $node-&gt;addChild(XmlNode-&gt;new('notice-text', 'content' =&gt; $phpSettingsPtr-&gt;{'notice'}));
    delete $phpSettingsPtr-&gt;{'notice'};
  }

  foreach my $key (keys %{$phpSettingsPtr}) {
    my $settingNode = XmlNode-&gt;new('setting');
    $settingNode-&gt;addChild(XmlNode-&gt;new('name', 'content' =&gt; $key));
    $settingNode-&gt;addChild(XmlNode-&gt;new('value', 'content' =&gt; $phpSettingsPtr-&gt;{$key}));
    $node-&gt;addChild($settingNode);
  }

  return $node;
}

sub makeIpNode {
  my ($self, $ip, $iptype) = @_;
  return XmlNode-&gt;new(
    'ip',
    'children' =&gt; [
      XmlNode-&gt;new( 'ip-type',    content =&gt; $iptype ),
      XmlNode-&gt;new( 'ip-address', content =&gt; $ip )
    ]
  );
}

sub addServerVirusfilter {
  my ($self, $virusfilter) = @_;

  my $root = $self-&gt;{serverNode};

  my $content = defined($virusfilter) ? $virusfilter : 'none';

  my $virusfilterNode = XmlNode-&gt;new('virusfilter', 'content' =&gt; $content);
  $virusfilterNode-&gt;setAttribute( 'state', defined($virusfilter) ? 'inout' : 'none' );

  $root-&gt;addChild($virusfilterNode);

  return $virusfilterNode;
}

sub getSb5SitePublished {
  my ($self, $name) = @_;

  my $sb5SitePublishedUtil = AgentConfig::sb5SitePublishedUtil();
  my $cmd = $sb5SitePublishedUtil . " --is-site-builder-site-published " . $name;
  Logging::debug("Exec: $cmd");
  my $result = `$cmd`;
  chomp($result);
  my $retCode = $? &gt;&gt; 8;
  if( $retCode != 0 ) {
    Logging::warning( "Unable to backup Site Builder publishing status on site $name (ErrorCode: $retCode, STDOUT:$result).", 'UtilityError' );
    return;
  }
  return ($result eq 'true')? 'true' : 'false';
}

sub setSb5ServerContent {
  my ($self) = @_;
  my $root = $self-&gt;{serverNode};
  my $sb5backupUtil = AgentConfig::sb5BackupUtil();

  unless (defined $sb5backupUtil)
  {
    Logging::debug("Unable to find SiteBuilder backup utility to create server content backup.");
    return;
  }

  my $dstFile = HelpFuncs::mktemp("pmm-sb5-sc-XXXXXXXX");
  my $cmd = "$sb5backupUtil --backup --target=server_settings --log=stdout --file=$dstFile";
  my $result = `$cmd`;
  my $retCode = $? &gt;&gt; 8;

  Logging::debug("Backing up sitebuilder server settings:");
  Logging::debug($cmd);
  Logging::debug($result);

  if( $retCode == 0 ) {
    if( -e "$dstFile.zip") {
      my $cid = $self-&gt;{content_transport}-&gt;addAdminContent('sb5-server', undef, 'sb_server', "directory" =&gt; ".", "include"   =&gt; [$dstFile.".zip"]);
      $root-&gt;getChild('content', 1, 1)-&gt;addChild($cid) if $cid;
    }
    else {
      Logging::warning( "Sitebuilder backup was not created.", 'UtilityError' );
    }
  }
  else {
    Logging::warning( "Return code of sitebuilder bru utility: ".$retCode.". Some errors occured during sitebuilder backup. Please see psadump.log file for more information", 'UtilityError' );
  }
  unlink "$dstFile.zip" if( -e "$dstFile.zip");
}

sub setSb5DomainContent {
  my ($self, $domainId, $domainName, $uuid) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my $sb5backupUtil = AgentConfig::sb5BackupUtil();
  unless (defined $sb5backupUtil)
  {
    Logging::debug("Unable to find SiteBuilder backup utility to create domain content backup.");
    return;
  }

  my $dstFile = HelpFuncs::mktemp("pmm-sb5-dc-XXXXXXXX");
  my $cmd = "$sb5backupUtil --backup --target=site --uuid=$uuid --log=stdout --file=$dstFile";
  my $result = `$cmd`;
  my $retCode = $? &gt;&gt; 8;

  Logging::debug("Backing up sitebuilder settings for site $domainName:");
  Logging::debug($cmd);
  Logging::debug($result);
  if( $retCode==0 ){
    if( -e "$dstFile.zip") {
      my $cid = $self-&gt;{content_transport}-&gt;addDomainContent('sb5-site', $domainId, 'sb_site', "directory" =&gt; ".", "include"   =&gt; [$dstFile.".zip"]);
      if ( $cid ) {
        my @phostings = $root-&gt;getChildren('phosting');
        if ( @phostings ) {
          $phostings[0]-&gt;getChild('content', 1, 1)-&gt;addChild($cid);
        }
        else {
          Logging::warning('Error: setSb5DomainContent: there are no node "phosting"', 'PackerStructure');
        }
      }
    }
    else {
      Logging::warning( "Sitebuilder backup was not created." , 'UtilityError' );
    }
  }
  else {
    Logging::warning( "Return code of sitebuilder bru utility: ".$retCode.". Some errors occured during sitebuilder backup. Please see psadump.log file for more information", 'UtilityError' );
  }
  unlink "$dstFile.zip" if( -e "$dstFile.zip");
}

sub setSmbSiteEditorDomainContent {
  my ($self, $domainId, $domainName ) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my $backupUtil = AgentConfig::sbbackupBin();
  my $dstFile = HelpFuncs::mktemp("pmm-siteeditor-XXXXXXXX");
  my $cmd = "$backupUtil --target=site --name=$domainName --log=stdout --file=$dstFile";
  my $result = `$cmd`;
  my $retCode = $? &gt;&gt; 8;

  Logging::debug("Backing up siteeditor settings for site $domainName:");
  Logging::debug($cmd);
  Logging::debug($result);
  if( $retCode==0 ){
    if( -e "$dstFile.zip") {
      my $cid = $self-&gt;{content_transport}-&gt;addDomainContent('sb-dump', $domainId, 'sb_dump', "directory" =&gt; ".", "include"   =&gt; [$dstFile.".zip"]);
	  if ( $cid ) {
        my @phostings = $root-&gt;getChildren('phosting');
        if ( @phostings ) {
          $phostings[0]-&gt;getChild('preferences', 1)-&gt;getChild('sb-domain', 1)-&gt;getChild('content', 1, 1)-&gt;addChild($cid);
        }
        else {
          Logging::warning('Error: setSmbSiteEditorDomainContent: there are no node "phosting"', 'PackerStructure');
        }
      }
    }
    else {
      Logging::warning( "SiteEditor backup was not created." , 'UtilityError' );
    }
  }
  else {
    Logging::warning( "Return code of SiteEditor sbbackup utility: ".$retCode.". Some errors occured during SiteEditor backup. Please see psadump.log file for more information", 'UtilityError' );
  }
  unlink "$dstFile.zip" if( -e "$dstFile.zip");
}

sub addFileSharingContent {
  my ($self, $path) = @_;
  my $root = $self-&gt;{serverNode};

  my $cid = $self-&gt;{content_transport}-&gt;addAdminContent('file-sharing', undef, 'file_sharing', 'directory' =&gt; $path, 'checkEmptyDir' =&gt; 1, 'exclude' =&gt; ['unlisted']);
  $root-&gt;getChild('content', 1, 1)-&gt;addChild($cid) if $cid;
}

sub addFileSharingPasswd {
  my ($self, $path) = @_;
  my $root = $self-&gt;{serverNode};

  my $cid = $self-&gt;{content_transport}-&gt;addAdminContent('file-sharing-passwd', undef, 'file_sharing_passwd', 'directory' =&gt; $path, 'checkEmptyDir' =&gt; 1 );
  $root-&gt;getChild('content', 1, 1)-&gt;addChild($cid) if $cid;
}

sub addServerCustomApacheTemplates {
  my ($self, $path) = @_;
  my $root = $self-&gt;{serverNode};

  my $dumpFile = $self-&gt;{content_transport}-&gt;addAdminContent('custom-apache-templates', undef, 'custom_apache_templates', 'directory' =&gt; $path);
  $root-&gt;getChild('content', 1, 1)-&gt;addChild($dumpFile) if $dumpFile;

}

sub addServerCustomHealthConfig {
  my ($self) = @_;
  my $root = $self-&gt;{serverNode};

  my $path = AgentConfig::get('PRODUCT_ROOT_D') . "/var";
  my $file = 'custom-health-config.xml';

  if ( -e "$path/$file") {
    my $dumpFile = $self-&gt;{content_transport}-&gt;addAdminContent('drilldowns-config', undef, 'dd_conf', 'directory' =&gt; $path, 'include' =&gt; [$file]);
    $root-&gt;getChild('content', 1, 1)-&gt;addChild($dumpFile) if $dumpFile;
  }
}

sub addCustomizationConfig {

  my ($self) = @_;
  my $root = $self-&gt;{serverNode};

  my $path = AgentConfig::get('PRODUCT_ROOT_D') . "/admin/conf";
  my $file = 'customizations.conf';

  if ( -e "$path/$file") {

    my $customizationNode = XmlNode-&gt;new('customization');

    my $configText = undef;

    open CONFIGFILE, $path . "/" . $file;
    binmode(CONFIGFILE);

    while (&lt;CONFIGFILE&gt;) {
      $configText .= $_;
    }

    close CONFIGFILE;

    $customizationNode-&gt;addChild(XmlNode-&gt;new('config', 'content' =&gt; $self-&gt;{base64}-&gt;{'ENCODE'}-&gt;($configText) ));
    $root-&gt;addChild($customizationNode);
  }
}

sub addRestrictedDomains {
  my ($self) = @_;
  my $root = $self-&gt;{serverNode};
  my @restrictedDomains = @{DAL::getRestrictedDomains()};

  if ( @restrictedDomains ) {
    my $restrictedDomainNode = XmlNode-&gt;new('restricted-domains');

    foreach my $domain (@restrictedDomains) {
        $restrictedDomainNode-&gt;addChild(XmlNode-&gt;new('hostname', 'content' =&gt; $domain-&gt;{'name'}));
    }

    $root-&gt;addChild($restrictedDomainNode);
  }
}

sub addFail2ban {
  my ($self) = @_;

  my %packages = %{DAL::getSoftwarePackages()};
  if (!exists($packages{'fail2ban'})) {
    return;
  }

  my $fail2banNode = XmlNode-&gt;new('fail2ban');
  $fail2banNode-&gt;setAttribute('version', $packages{'fail2ban'});

  my $fail2banDir = '/etc/fail2ban';
  my @includeList = ('action.d/', 'filter.d/', 'jail.d/', 'jail.conf');
  for my $localConfig ( ('jail.local', 'fail2ban.local') ) {
    if (-e "$fail2banDir/$localConfig") {
      push(@includeList, $localConfig);
    }
  }

  my $cid = $self-&gt;{content_transport}-&gt;addAdminContent(
    'fail2ban',
    undef,
    'fail2ban',
    'directory' =&gt; $fail2banDir,
    'include' =&gt; \@includeList,
    'skip_content' =&gt; 0,
  );
  $fail2banNode-&gt;getChild('content', 1, 1)-&gt;addChild($cid) if $cid;

  $self-&gt;{serverNode}-&gt;addChild($fail2banNode);
}

sub addModSecurityContent {
  my ($self, $rulesBaseDir, @ruleSetDirs) = @_;

  my $cid = $self-&gt;{content_transport}-&gt;addAdminContent(
    'modsecurity',
    undef,
    'modsecurity',
    'directory' =&gt; $rulesBaseDir,
    'include' =&gt; \@ruleSetDirs,
    'skip_content' =&gt; 0
  );
  $self-&gt;{serverNode}-&gt;getChild('content', 1, 1)-&gt;addChild($cid) if $cid;
}

sub dumpUnityMobileIntegration {
  my ($self, $domainId, $ptrDomParams) = @_;

  my %domParams = %{$ptrDomParams};

  if ( defined $domParams{'unity_mobile_site_dns_target'}
       and defined $domParams{'unity_mobile_site_key'}
       and defined $domParams{'unity_mobile_site_prefix'}
  ) {

    my $root = $self-&gt;getCashedDomainNode($domainId);

    my $umNode = XmlNode-&gt;new('unity-mobile-integration');
    my $siteNode = XmlNode-&gt;new('mobile-site');
    $siteNode-&gt;addChild(XmlNode-&gt;new('dns-target', 'content' =&gt; $domParams{'unity_mobile_site_dns_target'}));
    $siteNode-&gt;addChild(XmlNode-&gt;new('key', 'content' =&gt; $domParams{'unity_mobile_site_key'}));
    $siteNode-&gt;addChild(XmlNode-&gt;new('prefix', 'content' =&gt; $domParams{'unity_mobile_site_prefix'}));
    $umNode-&gt;addChild($siteNode);
    $root-&gt;getChild( 'preferences', 1 )-&gt;addChild($umNode);
  }
}

sub makeApsBundleFilterNode {
  my ($self, $parentId, $parentType, $filterType, $filterItems, $parentNode) = @_;

  my $apsBundleNode = XmlNode-&gt;new('aps-bundle');

  my $filterNode = XmlNode-&gt;new('filter', 'attributes' =&gt; { 'type' =&gt; $filterType});
  $apsBundleNode-&gt;addChild($filterNode);

  foreach my $itemHash (@{$filterItems}) {
    my ($name, $value) = each %{$itemHash};
    my $itemNode = XmlNode-&gt;new('item');
    $itemNode-&gt;addChild(XmlNode-&gt;new('name', 'content' =&gt; $name));
    $itemNode-&gt;addChild(XmlNode-&gt;new('value', 'content' =&gt; $value));
    $filterNode-&gt;addChild($itemNode);
  }

  if (!defined($parentNode)) {
    if ($parentType eq 'client') {
      $parentNode = $self-&gt;getCashedClientNode($parentId);
    }elsif ($parentType eq 'domain') {
      $parentNode = $self-&gt;getCashedDomainNode($parentId);
    }

    $parentNode-&gt;getChild('preferences', 1)-&gt;addChild($apsBundleNode);
  }else{
    $parentNode-&gt;addChild($apsBundleNode);
  }
}

sub makeSkinNode {
  my ($self, $skinName, $login, $id) = @_;
  $self-&gt;makeBrandingCid($id, $login, "-name " . $skinName, "theme-skin") if $skinName ne '';
}

sub makeBrandingCid {
  my ($self, $id, $login, $cmdArgs, $cidType) = @_;

  my $parentNode;
  if (defined $id) {
    $parentNode = $self-&gt;{resellersNodes}-&gt;{$id};
  }else {
    $parentNode = $self-&gt;{serverNode};
  }

  my $command = AgentConfig::brandingUtil();
  my $dstFile = HelpFuncs::mktemp("pmm-brandtheme-XXXXXXXX");

  if (defined $command) {
      my $cmd = $command . " --pack " . $cmdArgs . " -destination " . $dstFile;
      Logging::debug("Exec: $cmd");
      my $ret = `$cmd`;
      my $retCode = $? &gt;&gt; 8;
      if( $retCode!=0 and $retCode != 13){
        Logging::warning( "Cannot pack theme for vendor " . $login . "STDOUT:" . $ret,'UtilityError');
        return;
      }
      if ( -e $dstFile) {
        my $cid = undef;
        if (defined $id) {
          $cid = $self-&gt;{content_transport}-&gt;addClientContent($cidType, $id, 'branding', 'directory' =&gt; '.', 'include' =&gt; [$dstFile]);
        }else{
          $cid = $self-&gt;{content_transport}-&gt;addAdminContent($cidType, undef, 'branding', 'directory' =&gt; '.', 'include' =&gt; [$dstFile]);
        }
        if ($cid) {
          $parentNode-&gt;getChild('content', 1, 1)-&gt;addChild($cid);
        }
      }
  } else {
    Logging::warning( "Utility for dumping branding theme is unavailable ", 'UtilityError');
    unlink $dstFile if ( -e $dstFile);
    return;
  }
  unlink $dstFile if ( -e $dstFile);
}

sub addCrontabSecureSettings {
  my ($self, $params) = @_;
  my $serverNode = $self-&gt;{serverNode};
  my $serverPrefNode = $serverNode-&gt;getChild( 'server-preferences', 1 );
  $serverPrefNode-&gt;addChild(XmlNode-&gt;new('crontab-secure-shell', 'content' =&gt; $params-&gt;{'crontab_secure_shell'})) if defined $params-&gt;{'crontab_secure_shell'};
  $serverPrefNode-&gt;addChild(XmlNode-&gt;new('crontab-secure-shell-compatibility-mode', 'content' =&gt; $params-&gt;{'crontab_secure_shell_compatibility_mode'} eq 'true' ? 'true' : 'false')) if defined $params-&gt;{'crontab_secure_shell_compatibility_mode'};
}

sub addKavSettingsParam {
  my ($self, $kavSettingsNode, $param, $value) = @_;

  my %allowedParams = (
      'Check' =&gt; 1,
      'AddXHeaders' =&gt; 1,
      'AdminAddress' =&gt; 1,
      'QuarantinePath' =&gt; 1,
      'FilterByName' =&gt; 1,
      'FilterByMIME' =&gt; 1,
      'SkipByName' =&gt; 1,
      'SkipByMIME' =&gt; 1,
      'Quarantine' =&gt; 1,
      'AdminNotify' =&gt; 1,
      'AdminAction' =&gt; 1,
      'SenderNotify' =&gt; 1,
      'RecipientNotify' =&gt; 1,
      'RecipientAttachReport' =&gt; 1,
      'RecipientAction' =&gt; 1,
      'CuredAdminAction' =&gt; 1,
      'CuredRecipientAction' =&gt; 1,
      'InfectedAdminAction' =&gt; 1,
      'SuspiciousAdminAction' =&gt; 1,
      'InfectedRecipientAction' =&gt; 1,
      'SuspiciousRecipientAction' =&gt; 1,
      'FilteredRecipientAction' =&gt; 1,
      'FilteredQuarantine' =&gt; 1
    );

  if ( $allowedParams{$param} ) {
    $kavSettingsNode-&gt;addChild( XmlNode-&gt;new( 'param', 'content' =&gt; $value, 'attributes' =&gt; { 'name' =&gt; $param } ) );
  }
  return;
}

sub makeSubscriptionNode {
  my ($self, $locked, $synchronized, $custom, $externalId) = @_;

  my $subscriptionNode = XmlNode-&gt;new( 'subscription' );

  if (defined $locked) {
    $subscriptionNode-&gt;setAttribute('locked', $locked);
  }

  if (defined $custom) {
    $subscriptionNode-&gt;setAttribute('custom', $custom);
  }

  if (defined $externalId and $externalId ne '') {
    $subscriptionNode-&gt;setAttribute('external-id', $externalId);
  }

  if (defined $synchronized) {
    $subscriptionNode-&gt;setAttribute('synchronized', $synchronized);
  }

  return $subscriptionNode;
}

sub addSubscriptionPlan {
  my ($self, $subscriptionNode, $quantity, $plan_guid, $is_addon) = @_;

  return unless ( ( defined $quantity ) &amp;&amp; ( defined $plan_guid ) );
  my $planNode = XmlNode-&gt;new( 'plan' );
  $planNode-&gt;setAttribute('quantity', $quantity);
  $planNode-&gt;setAttribute('plan-guid', $plan_guid);
  if ( defined $is_addon) {
    $planNode-&gt;setAttribute('is-addon', $is_addon);
  }
  $subscriptionNode-&gt;addChild($planNode);
  return;
}

sub dumpFileSharingServerSettings {
  my ($self, $settingsPtr) = @_;

  my %settings = %{$settingsPtr};

  my $fsNode = XmlNode-&gt;new('file-sharing-settings');

  my $parentNode = $self-&gt;{serverNode};

  foreach my $key (keys %settings) {
    $fsNode-&gt;addChild(XmlNode-&gt;new('setting','attributes' =&gt;
      { 'name' =&gt; $key, 'value' =&gt; $settings{$key}} ) );
  }
  $parentNode-&gt;addChild($fsNode);
}

sub dumpFileSharingUnlistedFiles {
  my ($self, $unlistedFiles) = @_;

  my $unlistedFilesNode = XmlNode-&gt;new('file-sharing-unlisted-files');
  foreach my $unlistedFile (@{$unlistedFiles}) {
    $unlistedFilesNode-&gt;addChild(XmlNode-&gt;new('file-sharing-unlisted-file','attributes' =&gt; {
      'creation-date' =&gt; $unlistedFile-&gt;{'creationDate'},
      , 'salt' =&gt; $unlistedFile-&gt;{'salt'}
      , 'name' =&gt; $unlistedFile-&gt;{'name'}
      , 'path' =&gt; $unlistedFile-&gt;{'path'}
      , 'expiration' =&gt; $unlistedFile-&gt;{'expiration'}
    }));
  }
  $self-&gt;{serverNode}-&gt;addChild($unlistedFilesNode);
}

sub dumpUiMode {
  my ($self, $paramsPtr) = @_;

  my %params = %{$paramsPtr};

  my $parent = $self-&gt;{serverNode};

  my $uiMode = undef;

  if (!defined($params{'power_user_panel'}) || $params{'power_user_panel'} ne 'true') {
    $uiMode = 'classic';
  } else {
    if (defined $params{'simple_panel'} &amp;&amp; $params{'simple_panel'} eq 'true') {
      $uiMode = (defined $params{'simple_panel_lock'} &amp;&amp; $params{'simple_panel_lock'} eq 'true') ? 'simple-lock' : 'simple';
    } else {
      $uiMode = 'normal';
    }
  }

  if (defined $uiMode) {
    $parent-&gt;getChild( 'interface-preferences', 1 )-&gt;addChild(XmlNode-&gt;new('ui-mode', 'content' =&gt; $uiMode));
  }
}

sub addTechnicalPreviewDomainNode {
  my ($self, $domainName) = @_;
  my $serverNode = $self-&gt;{serverNode};
  my $serverPrefNode = $serverNode-&gt;getChild( 'server-preferences', 1 );
  $serverPrefNode-&gt;addChild(XmlNode-&gt;new('technical-domain', 'content' =&gt; $domainName));
}

sub addUpdateSettings {
  my ($self, $autoUpdatesValue, $autoUpgradeToStable, $autoUpgradeBranch) = @_;

  my $serverNode = $self-&gt;{serverNode};
  my $serverPrefNode = $serverNode-&gt;getChild( 'server-preferences', 1 );
  my $updateSettingsNode = XmlNode-&gt;new('update-settings');
  $updateSettingsNode-&gt;addChild(XmlNode-&gt;new('autoupdates', 'content' =&gt; $autoUpdatesValue));
  $updateSettingsNode-&gt;addChild(XmlNode-&gt;new('autoupgrade-stable', 'content' =&gt; $autoUpgradeToStable));
  $updateSettingsNode-&gt;addChild(XmlNode-&gt;new('release-tier', 'content' =&gt; $autoUpgradeBranch));

  $serverPrefNode-&gt;addChild($updateSettingsNode);
}

sub addFtpOverSslSettings {
  my ($self, $value) = @_;
  
  my $serverNode = $self-&gt;{serverNode};
  my $serverPrefNode = $serverNode-&gt;getChild( 'server-preferences', 1 );
  $serverPrefNode-&gt;addChild(XmlNode-&gt;new('ftp-over-ssl', 'content' =&gt; $value));
}

sub setMiscParameters {
  my ($self, $paramsPtr) = @_;

  my $serverNode = $self-&gt;{serverNode};
  my %params = %{$paramsPtr};

  my $miscNode = $serverNode-&gt;getChild( 'misc', 1 );

  foreach my $name (keys %params) {
    my $paramNode = XmlNode-&gt;new('param');
    $paramNode-&gt;addChild(XmlNode-&gt;new('name', 'content' =&gt; $name));
    $paramNode-&gt;addChild(XmlNode-&gt;new('value', 'content' =&gt; $params{$name}));
    $miscNode-&gt;addChild($paramNode);
  }
}

sub _getChildNodeName {
  my ($self, $parentNodeName) = @_;

  my %nodesMapping = (
    'components' =&gt; 'component'
    , 'resource-usage' =&gt; 'resource'
    , 'miscellaneous' =&gt; 'setting'
    , 'apache-modules' =&gt; 'module'
  );

  return $nodesMapping{$parentNodeName};
}

sub _makeNameValueNode {
  my ($self, $nodeName, $name, $value) = @_;

  my $node = XmlNode-&gt;new($nodeName);
  my $nameNode = XmlNode-&gt;new('name', 'content' =&gt; $name);
  my $valueNode = XmlNode-&gt;new('value', 'content' =&gt; $value);
  $node-&gt;addChild($nameNode);
  $node-&gt;addChild($valueNode);

  return $node;
}

sub makeDomainParamsNode {
  my ($self, $domainId, $domainParams) = @_;

  my $root = $self-&gt;getCashedDomainNode($domainId);
  return unless defined $root;

  my $properties = $root-&gt;getChild( 'properties', 1 );
  my $domParam = XmlNode-&gt;new('dom-param');
  foreach my $key (keys %{$domainParams}) {
    $domParam-&gt;addChild($self-&gt;_makeNameValueNode('param', $key, $self-&gt;{base64}-&gt;{'ENCODE'}-&gt;($domainParams-&gt;{$key})));
  }
  $properties-&gt;addChild($domParam);
}

sub makeSubscriptionPropertiesNode {
  my ($self, $parentNode, $subscriptionProperties) = @_;

  my $propertiesNode = XmlNode-&gt;new('properties');
  foreach my $key (keys %{$subscriptionProperties}) {
    $propertiesNode-&gt;addChild($self-&gt;_makeNameValueNode('property', $key, $self-&gt;{base64}-&gt;{'ENCODE'}-&gt;($subscriptionProperties-&gt;{$key})));
  }
  $parentNode-&gt;addChild($propertiesNode);
}

sub assignApplicationInfoToMailUser {
  my ($self, $applicationApsRegistryId, $resourceInfo) = @_;

  my $mailUserNode = $self-&gt;{mailNodes}-&gt;{$resourceInfo-&gt;{'id'}};
  return unless defined $mailUserNode;

  my $apsServices = $mailUserNode-&gt;getChild('aps-services', 1);

  my $apsService = XmlNode-&gt;new('aps-service');
  $apsService-&gt;addChild(XmlNode-&gt;new('application-registry-id', 'content' =&gt; $applicationApsRegistryId));
  $apsService-&gt;addChild(XmlNode-&gt;new('resource-registry-id', 'content' =&gt; $resourceInfo-&gt;{'apsRegistryId'}));

  $apsServices-&gt;addChild($apsService);
}

sub makeDomainDescriptionsNode {
  my ( $self, $domainId, $description ) = @_;

  my $domainNode = $self-&gt;getCashedDomainNode( $domainId );
  my $prefs = $domainNode-&gt;getChild( 'preferences', 1 );

  $self-&gt;makeDescriptionsNode( $prefs, [{ 'description' =&gt; $description }] );
}

sub makeMailUserDescriptionNode {
  my ( $self, $mailUserId, $description ) = @_;

  my $mailUserNode = $self-&gt;{mailNodes}-&gt;{$mailUserId};
  my $prefs = $mailUserNode-&gt;getChild( 'preferences', 1 );

  $self-&gt;makeDescriptionsNode( $prefs, [{ 'description' =&gt; $description }] );
}

sub makeResellerDescriptionsNode {
  my ( $self, $resellerId, $descriptions ) = @_;

  my $resellerNode = $self-&gt;{resellersNodes}-&gt;{$resellerId};

  my $prefs = $resellerNode-&gt;getChild( 'preferences', 1 );

  $self-&gt;makeDescriptionsNode( $prefs, $descriptions );
}

sub makeDescriptionsNode {
  my ( $self, $parentNode, $descriptions ) = @_;

  if ( scalar @{$descriptions} &gt; 0 ) {
    my $descriptionsNode = XmlNode-&gt;new( 'descriptions' );
    foreach my $description ( @{$descriptions} ) {
      my $descriptionNode = XmlNode-&gt;new( 'description', 'content' =&gt; $description-&gt;{'description'} );
      $descriptionNode-&gt;setAttribute( 'object-name', $description-&gt;{'name'}) if $description-&gt;{'name'} and $description-&gt;{'name'} ne '';
      $descriptionNode-&gt;setAttribute( 'object-type', $description-&gt;{'type'}) if $description-&gt;{'type'} and $description-&gt;{'type'} ne '';
      $descriptionsNode-&gt;addChild( $descriptionNode );
    }
    $parentNode-&gt;addChild( $descriptionsNode );
  }
}

sub makeOutgoingMessagesParameter {
    my ($self, $objectType, $objectDbId, $paramName, $paramValue) = @_;

    my $object = $self-&gt;_getObject($objectType, $objectDbId);
    $object-&gt;getChild('preferences', 1)-&gt;getChild('outgoing-messages', 1)-&gt;addChild(XmlNode-&gt;new('parameter', 'children' =&gt; [
        XmlNode-&gt;new('name', 'content' =&gt; $paramName),
        XmlNode-&gt;new('value', 'content' =&gt; $paramValue),
    ]));
}

sub _makeSeverOutgoingEmailMode {
    my ($self, $mailSettingsPtr, $ipAddressesPtr) = @_;
    my %mailSettings = %{$mailSettingsPtr};
    my %ipAddresses = %{$ipAddressesPtr};
    if (!defined($mailSettings{'outgoing_email_mode'})) {
        return;
    }

    my $outgoingEmailMode = $mailSettings{'outgoing_email_mode'};
    Logging::debug("outgoing_email_mode found: $outgoingEmailMode");
    if ($outgoingEmailMode eq 'domain-ip' || $outgoingEmailMode eq 'domain-name') {
        $self-&gt;{serverNode}-&gt;getChild('mail-settings', 1)-&gt;addChild(XmlNode-&gt;new('outgoing-email-mode', 'children' =&gt; [
            XmlNode-&gt;new($outgoingEmailMode)
        ]));
    } elsif ($outgoingEmailMode == 'explicit-ip') {
        my @ips;
        for my $param ('outgoing_email_mode_explicit_ip_v4', 'outgoing_email_mode_explicit_ip_v6') {
            if (defined($mailSettings{$param}) &amp;&amp; $mailSettings{$param} ne ''
                &amp;&amp; defined($ipAddresses{$mailSettings{$param}})) {
                push @ips, XmlNode-&gt;new('ip-address', 'content' =&gt; $ipAddresses{$mailSettings{$param}}-&gt;{'ip_address'});
            }
        }
        $self-&gt;{serverNode}-&gt;getChild('mail-settings', 1)-&gt;addChild(XmlNode-&gt;new('outgoing-email-mode', 'children' =&gt; [
            XmlNode-&gt;new($outgoingEmailMode, 'children' =&gt; \@ips)
        ]));
    }
}

sub _makeServerOutgoingMessagesParameter {
    my ($self, $paramName, $paramValue) = @_;

    $self-&gt;{serverNode}-&gt;getChild('mail-settings', 1)-&gt;getChild('outgoing-messages', 1)-&gt;addChild(
        XmlNode-&gt;new('parameter', 'children' =&gt; [
            XmlNode-&gt;new('name', 'content' =&gt; $paramName),
            XmlNode-&gt;new('value', 'content' =&gt; $paramValue),
        ]
    ));
}

# Method return object by their types and id
# returns XmlNode | undef
sub _getObject{
    my ($self, $objectType, $objectDbId) = @_;

    if ($objectType eq 'admin') {
        return $self-&gt;{admin};
    } elsif ($objectType eq 'server') {
        return $self-&gt;{serverNode};
    } elsif ($objectType eq 'reseller') {
        return $self-&gt;{resellersNodes}-&gt;{$objectDbId};
    } elsif ($objectType eq 'client' or $objectType eq 'customer') {
        return $self-&gt;{clientNodes}-&gt;{$objectDbId};
    } elsif ($objectType eq 'domain' or $objectType eq 'subscription' or $objectType eq 'site' ) {
        return $self-&gt;getCashedDomainNode($objectDbId);
    } elsif ($objectType eq 'mailsystem') {
        return $self-&gt;getCashedDomainNode($objectDbId)-&gt;getChild('mailsystem', 1);
    } elsif ($objectType eq 'mailuser') {
        return $self-&gt;{mailNodes}-&gt;{$objectDbId};
    } else {
        Logging::error("Object type \"$objectType\" is not supported by Packer::_getObject");
    }
    return undef;
}

sub makeClParamNode {
  my ( $self, $clientId, $clientType, $params ) = @_;

  my $parentNode = $self-&gt;_getObject($clientType, $clientId)-&gt;getChild('properties', 1)-&gt;getChild('cl-param', 1);
  foreach my $param ( keys( %{$params} ) ) {
    my $paramNode = XmlNode-&gt;new( 'param' );
    $paramNode-&gt;addChild( XmlNode-&gt;new( 'name', 'content' =&gt; $param ) );
    $paramNode-&gt;addChild( XmlNode-&gt;new( 'value', 'content' =&gt; $self-&gt;{base64}-&gt;{'ENCODE'}-&gt;( $params-&gt;{$param} ) ) );
    $parentNode-&gt;addChild( $paramNode );
  }
}


sub makeExtensionNode {
  my ($self, $objectType, $objectId) = @_;
  Logging::debug("makeExtensionNode $objectType, $objectId");
  $objectType = 'customer' if $objectType eq 'client';
  $objectType = 'subscription' if $objectType eq 'domain';

  my $extensionsHooks =  PleskStructure::getExtensionsHooks();
  foreach my $extId (keys %{$extensionsHooks}) {
    Logging::debug("Check extension $extId");
    next if $extensionsHooks-&gt;{$extId}-&gt;{$objectType} ne 'true';

    my $xml = DAL::backupExtension( $extId, $objectType, $objectId );
    return if not defined $xml;
    my $extName = $xml-&gt;{'name'};
    my $extension = XmlNode-&gt;new( 'extension',
        'attributes' =&gt; {
            'name'    =&gt; $extName,
            'version' =&gt; $xml-&gt;{'version'},
            'release' =&gt; $xml-&gt;{'release'},
        }
    );
    if (exists $xml-&gt;{'config'}) {
      $extension-&gt;addChild(XmlNode-&gt;new('config', 'content' =&gt; $xml-&gt;{'config'}[0]));
    }
    if (exists $xml-&gt;{'enabled'}) {
      $extension-&gt;setAttribute('enabled', $xml-&gt;{'enabled'});
    }
    if (exists $xml-&gt;{'settings'} and ref($xml-&gt;{'settings'}[0]) eq "HASH") {
      foreach my $setting (@{$xml-&gt;{'settings'}[0]-&gt;{'setting'}})
      {
        $extension-&gt;getChild( 'settings', 1 )-&gt;addChild( XmlNode-&gt;new( 'setting', 'children' =&gt; [
                    XmlNode-&gt;new( 'name', 'content' =&gt; $setting-&gt;{'name'}[0] ),
                    XmlNode-&gt;new( 'value', 'content' =&gt; $setting-&gt;{'value'}[0] ),
                ] ) );
      }
    }
    if (exists $xml-&gt;{'content'}) {
      my @include;
      my @exclude;
      my $packageFile;
      if (ref($xml-&gt;{'content'}) eq "HASH") {
        foreach my $item (@{$xml-&gt;{'content'}-&gt;{'include'}}) {
          $item =~ s/^[\\\/]*//;
          push @include, $item;
        }
        foreach my $item (@{$xml-&gt;{'content'}-&gt;{'exclude'}}) {
          $item =~ s/^[\\\/]*//;
          push @exclude, $item;
        }
        foreach my $item (@{$xml-&gt;{'content'}-&gt;{'webspace'}}) {
          $extension-&gt;getChild( 'webspace-paths', 1 )-&gt;addChild(XmlNode-&gt;new('path', 'content' =&gt; $item));
        }

        if (exists $xml-&gt;{'content'}-&gt;{'package'}) {
          $packageFile = $xml-&gt;{'content'}-&gt;{'package'}[0];
        }
      }

      if (scalar(@include) &gt; 0) {
        if ("." ~~ @include) {
          @include = ();
        }
        my $proc;
        if ($objectType eq 'admin' or $objectType eq 'server') { $proc = \&amp;addAdminContentProxy; }
        elsif ($objectType eq 'customer' or $objectType eq 'reseller') { $proc = \&amp;addClientContentProxy; }
        elsif ($objectType eq 'subscription' or $objectType eq 'site') { $proc = \&amp;addDomainContentProxy; }
        else {
          Logging::warning( "Error: makeExtensionNode: unsupported parent type '$objectType' ", 'assert' );
        }
        if ($proc) {
          my $cid = $self-&gt;$proc(
              'extension',
              $objectId,
              'ext_'.$extName,
              "directory"            =&gt; AgentConfig::get( 'PRODUCT_ROOT_D' )."/var/modules/$extName",
              "include"              =&gt; \@include,
              "exclude"              =&gt; \@exclude,
              "include_hidden_files" =&gt; 1
          );
          $extension-&gt;getChild( 'content', 1, 1 )-&gt;addChild( $cid ) if $cid;
        }
      }

      if (defined $packageFile &amp;&amp; -e $packageFile) {
        my $cid = $self-&gt;addAdminContentProxy(
            'extension_dist',
            $objectId,
            'ext_dist_'.$extName,
            "directory" =&gt; dirname($packageFile),
        );
        $extension-&gt;getChild( 'content', 1, 1 )-&gt;addChild( $cid ) if $cid;
        eval {
          File::Path::rmtree(dirname($packageFile));
        };
        Logging::debug('Unable to remove temporary directory with extension archive. ' . $@) if $@;
      }


    }
    $self-&gt;_getObject( $objectType, $objectId )-&gt;getChild( 'extensions', 1 )-&gt;addChild( $extension );
    if ($extensionsHooks-&gt;{$extId}-&gt;{"$objectType-post-backup"} eq 'true') {
      DAL::postBackupExtension( $extId, $objectType, $objectId );
    }
  }
}

1;
</pre></body></html>