Server IP : 195.201.23.43 / Your IP : 3.22.187.118 Web Server : Apache System : Linux webserver2.vercom.be 5.4.0-192-generic #212-Ubuntu SMP Fri Jul 5 09:47:39 UTC 2024 x86_64 User : kdecoratie ( 1041) PHP Version : 7.1.33-63+ubuntu20.04.1+deb.sury.org+1 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals, MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /usr/share/webmin/virtual-server/ |
Upload File : |
# Functions for migrating a cpanel backup # migration_cpanel_validate(file, domain, [user], [&parent], [prefix], [pass]) # Make sure the given file is a cPanel backup, and contains the domain sub migration_cpanel_validate { local ($file, $dom, $user, $parent, $prefix, $pass) = @_; local ($ok, $root) = &extract_cpanel_dir($file); $ok || return ("Not a cPanel tar.gz file : $root"); local $daily = glob("$root/backup*/cpbackup/daily"); local ($homedir) = glob("$root/*/homedir"); $homedir = "$root/homedir" if (!-d $homedir); local $datastore = "$root/.cpanel-datastore"; $datastore = "$root/.cpanel/datastore" if (!-d $datastore); -d $daily || -d $homedir || -d $datastore || return ("Not a cPanel daily or home directory backup file"); # Try to work out the domain if (!$dom) { local @domfiles = glob("$root/*/vf/*"); if (!@domfiles) { @domfiles = glob("$root/vf/*"); } local @doms = map { /\/vf\/([^\/]+)$/; $1 } @domfiles; if (@doms > 1) { # Hack to work out primary domain local $ds = "$homedir/.cpanel-datastore"; $ds = $datastore if (!-d $ds); opendir(DATASTORE, $ds); foreach my $gdi (readdir(DATASTORE)) { if ($gdi =~ /^apache_GETDOMAINIP_(\S+)$/) { $gdi{$1} = 1; } } closedir(DATASTORE); if (scalar(keys %gdi)) { # Can limit by domain IP to find the master @doms = grep { $gdi{$_} } @doms; } else { # Look at the cp/username file local ($cpfile) = glob("$root/*/cp/*"); if ($cpfile && -r $cpfile) { local %cp; &read_env_file($cpfile, \%cp); @doms = ( $cp{'DNS'} ); } } } if (@doms == 1) { $dom = $doms[0]; } elsif (@doms > 1) { return ("More than one domain name was found in the cPanel backup : ".join(" ", @doms)); } else { return ("Could not work out domain name from cPanel backup"); } } if (-d $daily) { # Older style backup - check for user and Apache domain file if (!$user) { local ($tgz) = glob("$daily/*.tar.gz"); $tgz =~ /\/([^\/]+)\.tar\.gz$/ || return ("Could not work out username from cPanel backup"); $user = $1; } -r "$daily/$user.tar.gz" || return ("Could not find directory for $user in backup"); local $httpd = &extract_cpanel_file("$daily/files/_etc_httpd_conf_httpd.conf.gz"); local ($vconf, $virt) = &get_apache_virtual($dom, undef, $httpd); $vconf || return ("Could not find Apache virtual server $dom in backup"); } elsif (-d $homedir) { # Newer style backup - check for aliases file ($vfdom) = glob("$root/*/vf/$dom"); -r $vfdom || return ("Could not find mail aliases file for $dom in backup"); if (!$user && $homedir =~ /\/backup-([^\/]+)_([^\/]+)\//) { $user = $2; } if (!$user && $homedir =~ /\/cpmove-([^\/]+)\//) { $user = $1; } if (!$user) { opendir(ROOT, $root); local @rootfiles = grep { !/^\./ } readdir(ROOT); closedir(ROOT); $user = $rootfiles[0]; } $user || return ("Could not work out username from cPanel backup"); } else { # Home-only backup $user || return ("Username must be supplied for this type of cPanel backup"); } # Password is needed for cPanel migrations if (!$parent && !$pass) { return ("A password must be supplied for cPanel migrations"); } return (undef, $dom, $user, $pass); } # migration_cpanel_migrate(file, domain, username, create-webmin, template-id, # &ipinfo, pass, [&parent], [prefix], [email]) # Actually extract the given cPanel backup, and return the list of domains # created. sub migration_cpanel_migrate { local ($file, $dom, $user, $webmin, $template, $ipinfo, $pass, $parent, $prefix, $email) = @_; local ($ok, $root) = &extract_cpanel_dir($file); $ok || &error("Failed to extract backup : $root"); local $daily = glob("$root/backup*/cpbackup/daily"); local $datastore = "$root/.cpanel-datastore"; $datastore = "$root/.cpanel/datastore" if (!-d $datastore); local $tmpl = &get_template($template); # Check for prefix clash $prefix ||= &compute_prefix($dom, undef, $parent, 1); local $pclash = &get_domain_by("prefix", $prefix); $pclash && &error("A virtual server using the prefix $prefix already exists"); # Get shells for users local ($nologin_shell, $ftp_shell, undef, $def_shell) = &get_common_available_shells(); $nologin_shell ||= $def_shell; $ftp_shell ||= $def_shell; # Work out the username again if it wasn't supplied local $origuser; local ($homedir) = glob("$root/*/homedir"); $homedir = "$root/homedir" if (!-d $homedir); if (-d $daily) { local ($tgz) = glob("$daily/*.tar.gz"); $tgz =~ /\/([^\/]+)\.tar\.gz$/; $origuser = $1; } elsif (-d $homedir) { $homedir =~ /\/backup-([^\/]+)_([^\/]+)\//; $origuser = $2; } $user ||= $origuser; $user || &error("Could not work out username automatically"); local $group = $user; local $ugroup = $group; # First work out what features we have .. &$first_print("Checking for cPanel features .."); local @got = ( "dir", $parent ? () : ("unix"), &domain_has_website(), "logrotate" ); push(@got, "webmin") if ($webmin && !$parent); local $userdir; local $homesrc; if (-d $daily) { local $named = &extract_cpanel_file("$daily/files/_etc_named.conf.gz"); local $zone; if ($named) { push(@got, "dns"); } local $localdomains = &extract_cpanel_file("$daily/files/_etc_localdomains.gz"); if ($localdomains) { # Check for mail domain local $lref = &read_file_lines($localdomains); foreach my $l (@$lref) { push(@got, "mail") if ($l eq $dom); } } ($ok, $userdir) = &extract_cpanel_dir("$daily/$user.tar.gz"); $ok || return "Failed to extract user directory : $userdir"; $userdir .= "/".$user; -d $userdir || return "No user directory found - maybe username ". "$user is incorrect"; $homesrc = "$userdir/homedir"; } elsif (-d $datastore) { # For a home-based only backup, assume we have web, mail and DNS push(@got, "dns", "mail"); $userdir = $homesrc = $root; } else { # For a homedir only backup, assume we have web, mail and DNS push(@got, "dns", "mail"); if (-d "$root/$user") { # Sub-directory is named after user $userdir = "$root/$user"; } else { # Sub-directory has date-based name ($userdir) = glob("$root/*"); } -d $userdir || return "No user directory found - ". "maybe username $user is incorrect"; $homesrc = "$userdir/homedir"; $datastore = "$homesrc/.cpanel-datastore"; if (-d "$homesrc/.cpanel/datastore") { $datastore = "$homesrc/.cpanel/datastore"; } } # Work out if the original domain was a sub-server in cPanel local $waschild = 0; local $wasuser = $dom; $wasuser =~ s/\..*$//; local $aliasdom; if (-r "$datastore/apache_LISTMULTIPARKED_0") { # Sub-servers are in this config file. We can also work out the original # 'username' for the sub-directory. local $subs = &read_file_contents( "$datastore/apache_LISTMULTIPARKED_0"); if ($subs =~ /(\/[a-z0-9\.\-_\/]+)[^a-z0-9\.\-]+\Q$dom\E[^a-z0-9\.\-]+([a-z0-9\.\-]+)?/i) { $waschild = 1; my $wasdir = $1; $aliasdom = $2; if ($wasdir =~ /public_html\/(.*)$/) { $wasuser = $1; } $aliasdom = undef if ($aliasdom !~ /\./); # Data error } } elsif (-d "$homesrc/tmp/webalizer") { # Sub-servers had separate webalizer config $waschild = -d "$homesrc/tmp/webalizer/$dom" ? 1 : 0; } else { # Can't be sure, so guess $waschild = $parent ? 1 : 0; } # Check for Webalizer and AWstats local $webalizer = $waschild ? "$homesrc/tmp/webalizer/$dom" : "$homesrc/tmp/webalizer"; if (-d $webalizer) { push(@got, "webalizer"); } if (-r "$homesrc/tmp/awstats/awstats.$dom.conf") { push(@got, "virtualmin-awstats"); } if (-s "$userdir/mysql.sql" && !$waschild) { # Check for mysql local $mycount = 0; local $mydir = "$userdir/mysql"; local %dblist = map { $_, 1 } &get_cpanel_db_list("$userdir/mysql.sql", $user, $origuser); opendir(MYDIR, $mydir); while($myf = readdir(MYDIR)) { if ($myf =~ /^(\Q$user\E_\S*).sql$/ || $myf =~ /^(\Q$origuser\E_\S*).sql$/ || $myf eq "$user.sql" || $myf eq "$origuser.sql" || $myf =~ /^(\S+).sql$/ && $dblist{$1}) { $mycount++; } } closedir(MYDIR); push(@got, "mysql") if ($mycount); } if ($ipinfo->{'virt'}) { # Enable ProFTPd, if we have a private IP push(@got, "ftp"); } if ($ipinfo->{'virt'} && -s "$userdir/sslcerts/www.$dom.crt" && -s "$userdir/sslkeys/www.$dom.key") { # Enable SSL, if we have a private IP and if the key was found push(@got, &domain_has_ssl()); } # Look for mailing lists local ($ml, @lists); opendir(MM, "$userdir/mm"); foreach $ml (readdir(MM)) { if ($ml =~ /^(\S+)_\Q$dom\E$/) { push(@lists, $1); } } closedir(MM); if (@lists && &plugin_defined("virtualmin-mailman", "create_list")) { push(@got, "virtualmin-mailman"); } # Tell the user what we have got @got = &show_check_migration_features(@got); local %got = map { $_, 1 } @got; # Work out user and group IDs local ($gid, $ugid, $uid, $duser); if ($parent) { # UID and GID come from parent $gid = $parent->{'gid'}; $ugid = $parent->{'ugid'}; $uid = $parent->{'uid'}; $duser = $parent->{'user'}; $group = $parent->{'group'}; $ugroup = $parent->{'ugroup'}; } else { # IDs are allocated by setup_unix $uid = $gid = $ugid = undef; $duser = $user; } local $quota; if (-r "$userdir/quota") { # Get the quota (from home directory backup) open(QUOTA, "<$userdir/quota"); $quota = <QUOTA>; close(QUOTA); $quota = int($quota) * 1024; # cpanel quotas are in MB } elsif (-r "$datastore/quota_-v") { # Get the quota (from v10 backup) local $_; open(QUOTA, "<$datastore/quota_-v"); while(<QUOTA>) { if (/^\s+\S+\s+(\d+)\s+(\d+)\s+(\d+)/) { $quota = $2; } } close(QUOTA); } # Create the virtual server object local %dom; $prefix ||= &compute_prefix($dom, $group, $parent, 1); local $plan = $parent ? &get_plan($parent->{'plan'}) : &get_default_plan(); %dom = ( 'id', &domain_id(), 'dom', $dom, 'user', $duser, 'group', $group, 'ugroup', $ugroup, 'uid', $uid, 'gid', $gid, 'ugid', $ugid, 'owner', "Migrated cPanel server $dom", 'email', $email ? $email : $parent ? $parent->{'email'} : undef, 'dns_ip', $ipinfo->{'virt'} ? undef : &get_dns_ip($parent ? $parent->{'id'} : undef), $parent ? ( 'pass', $parent->{'pass'} ) : ( 'pass', $pass ), 'source', 'migrate.cgi', 'template', $template, 'plan', $plan->{'id'}, 'parent', $parent ? $parent->{'id'} : undef, 'reseller', $parent ? $parent->{'reseller'} : undef, 'prefix', $prefix, 'no_tmpl_aliases', 1, 'no_mysql_db', $got{'mysql'} ? 1 : 0, 'nocreationmail', 1, 'nocopyskel', 1, 'nocreationscripts', 1, 'parent', $parent ? $parent->{'id'} : undef, 'creation_type', 'migrate', 'migration_type', 'cpanel', ); &merge_ipinfo_domain(\%dom, $ipinfo); if (!$parent) { &set_limits_from_plan(\%dom, $plan); $dom{'quota'} = $quota; $dom{'uquota'} = $quota; &set_capabilities_from_plan(\%dom, $plan); } $dom{'db'} = &database_name(\%dom); foreach my $f (@features, &list_feature_plugins()) { $dom{$f} = $got{$f} ? 1 : 0; } &set_featurelimits_from_plan(\%dom, $plan); # Work out the master admin MySQL password if (open(MYSQL, "<$userdir/mysql.sql")) { while(<MYSQL>) { s/\r|\n//g; if (/^GRANT USAGE ON \*\.\* TO '(\S+)'\@'(\S+)' IDENTIFIED BY PASSWORD '(\S+)';/ && $1 eq $user) { $dom{'mysql_enc_pass'} = $3; } } close(MYSQL); } local $orighome; if (-d $daily) { # Work out home directory (use cpanel home by default) local $httpd = &extract_cpanel_file("$daily/files/_etc_httpd_conf_httpd.conf.gz"); local ($srcvconf, $srcvirt) = &get_apache_virtual($dom, undef, $httpd); $orighome = &apache::find_directive("DocumentRoot", $srcvirt); $orighome =~ s/\/public_html$//; } else { # Try to stick with cpanel home standard (/home/$user) if (!$waschild) { $orighome = "/home/$user"; } } if ($orighome && &is_under_directory($home_base, $orighome) && !$parent) { # Use same home directory as cPanel $dom{'home'} = $orighome; } else { # Use Virtualmin's home $dom{'home'} = &server_home_directory(\%dom, $parent); } # Set cgi directories to cpanel standard $dom{'cgi_bin_dir'} = "public_html/cgi-bin"; $dom{'cgi_bin_path'} = "$dom{'home'}/$dom{'cgi_bin_dir'}"; $dom{'cgi_bin_correct'} = 1; # So that setup_web doesn't fix it &set_provision_features(\%dom); &generate_domain_password_hashes(\%dom, 1); &complete_domain(\%dom); # Check for various clashes &$first_print("Checking for clashes and dependencies .."); $derr = &virtual_server_depends(\%dom); if ($derr) { &$second_print($derr); return ( ); } $cerr = &virtual_server_clashes(\%dom); if ($cerr) { &$second_print($cerr); return ( ); } &$second_print(".. all OK"); # Create the initial server &$first_print("Creating initial virtual server $dom .."); &$indent_print(); local $err = &create_virtual_server(\%dom, $parent, $parent ? $parent->{'user'} : undef); &$outdent_print(); if ($err) { &$second_print($err); return ( ); } else { &$second_print(".. done"); } local @rvdoms = ( \%dom ); # Extra homedir.tar if needed local $hometar = "$userdir/homedir.tar"; if (-r $hometar) { &$first_print("Extracting home directory TAR file .."); local $out; if (!-d $homesrc) { &make_dir($homesrc, 0755); } &execute_command("cd ".quotemeta($homesrc)." && ". &make_tar_command("xf", $hometar), undef, \$out, \$out); if ($?) { &$second_print(".. TAR failed : <tt>$out</tt>"); } else { &$second_print(".. done"); } &set_home_ownership(\%dom); } # Migrate Apache configuration if ($got{'web'} && -d $daily) { &$first_print("Copying Apache directives .."); if ($srcvconf) { # Copy any directives not set by Virtualmin local $conf = &apache::get_config(); local ($vconf, $virt) = &get_apache_virtual($dom, undef); local %dirs; foreach my $a (@$virt) { next if ($a->{'type'}); $dirs{$a->{'name'}}++; } $dirs{'ScriptAlias'} = 0; # Always copy this $dirs{'ServerAlias'} = 0; # and this $dirs{'BytesLog'} = 1; # Not supported $dirs{'User'} = 1; # Don't copy user-related $dirs{'Group'} = 1; # settings, as Virtualmin will $dirs{'SuexecUserGroup'} = 1; # have already set them local %vals; foreach my $a (@$srcvirt) { next if ($a->{'type'} || $dirs{$a->{'name'}}); if ($dom{'home'} ne $orighome) { $a->{'value'} =~ s/$orighome/$dom{'home'}/g; } push(@{$vals{$a->{'name'}}}, $a->{'value'}); } foreach my $an (keys %vals) { &apache::save_directive($an, $vals{$an}, $virt, $conf); } &$second_print(".. done"); ®ister_post_action(\&restart_apache) if (!$got{'ssl'}); } else { &$second_print(".. could not find Apache configuration"); } } elsif ($got{'web'}) { # Just adjust cgi-bin directory to match cPanel local $conf = &apache::get_config(); local ($virt, $vconf) = &get_apache_virtual($dom, undef); if ($virt) { &apache::save_directive("ScriptAlias", [ "/cgi-bin $dom{'home'}/public_html/cgi-bin" ], $vconf, $conf); &flush_file_lines($virt->{'file'}); ®ister_post_action(\&restart_apache) if (!$got{'ssl'}); } &save_domain(\%dom); &add_script_language_directives(\%dom, $tmpl, $dom{'web_port'}); } $dom{'cgi_bin_correct'} = 0; # So that it is computed from now on if ($got{&domain_has_ssl()}) { # Copy and use the SSL certs that came with the domain &$first_print("Copying SSL certificate and key .."); ©_source_dest("$userdir/sslcerts/www.$dom.crt", $dom{'ssl_cert'}); ©_source_dest("$userdir/sslcerts/www.$dom.key", $dom{'ssl_key'}); if ($got{'ssl'}) { ®ister_post_action(\&restart_apache, 1); } &$second_print(".. done"); } # Migrate DNS domain if ($got{'dns'} && -d $daily) { &$first_print("Copying and fixing DNS records .."); &require_bind(); local ($ok, $named) = &extract_cpanel_dir( "$daily/dirs/_var_named.tar.gz"); local $zsrcfile = &bind8::find_value("file", $zone->{'members'}); if (-r "$named/$zsrcfile") { &execute_command("cp ".quotemeta("$named/$zsrcfile")." ". quotemeta(&bind8::make_chroot($zdstfile))); local ($recs, $zdstfile) = &get_domain_dns_records_and_file(\%dom); foreach my $r (@$recs) { my $change = 0; if (($r->{'name'} eq $dom."." || $r->{'name'} eq "www.".$dom."." || $r->{'name'} eq "ftp.".$dom."." || $r->{'name'} eq "mail.".$dom.".") && $r->{'type'} eq 'A') { # Fix IP in domain record $r->{'values'} = [ $dom{'ip'} ]; $change++; } elsif ($r->{'name'} eq $dom."." && $r->{'type'} eq 'NS') { # Set NS record to this server local $master = $bconfig{'default_prins'} || &get_system_hostname(); $master .= "." if ($master !~ /\.$/); $r->{'values'} = [ $master ]; $change++; } if ($change) { &modify_dns_record($recs, $zdstfile, $r); } } &post_records_change(\%dom, $recs, $zdstfile); &$second_print(".. done"); ®ister_post_action(\&restart_bind); } else { &$second_print(".. could not find records file in backup!"); } } local $out; local $ht = &public_html_dir(\%dom); local $qht = quotemeta($ht); if ($waschild) { # Migrate web directory local $qhtsrc = "$homesrc/public_html/$wasuser"; &$first_print("Copying web pages to $ht .."); &execute_command("cd $qhtsrc && ". "(".&make_tar_command("cf", "-", "."). " | (cd $qht && ". &make_tar_command("xf", "-")."))", undef, \$out, \$out); } else { # Migrate home directory contents (except logs and mail) &$first_print("Copying home directory to $dom{'home'} .."); local $qhome = quotemeta($dom{'home'}); local $xtemp = &transname(); &open_tempfile(XTEMP, ">$xtemp"); &print_tempfile(XTEMP, "./logs\n"); &print_tempfile(XTEMP, "./mail\n"); &close_tempfile(XTEMP); &execute_command("cd $homesrc && ". "(".&make_tar_command("cfX", "-", $xtemp, "."). " | (cd $qhome && ". &make_tar_command("xf", "-")."))", undef, \$out, \$out); } if ($?) { &$second_print(".. copy failed : <tt>$out</tt>"); } else { &$second_print(".. done"); } &set_home_ownership(\%dom); # If php.ini is migrated wrong, fix it if ($dom{'web'}) { local $mode = &get_domain_php_mode(\%dom); if ($mode eq "cgi" || $mode eq "fcgid") { &fix_php_extension_dir(\%dom); } } # Fix up home ownership and permissions &$first_print("Fixing home directory permissions .."); if (defined(&set_php_wrappers_writable)) { &set_php_wrappers_writable(\%dom, 1); } &set_home_ownership(\%dom); &system_logged("chmod '$uconfig{'homedir_perms'}' ". quotemeta($dom{'home'})); foreach my $sd (&virtual_server_directories(\%dom)) { &system_logged("chmod $sd->[1] ". quotemeta("$dom{'home'}/$sd->[0]")); } if (defined(&set_php_wrappers_writable)) { &set_php_wrappers_writable(\%dom, 0); } &$second_print(".. done"); # Lock the user DB and build list of used IDs &obtain_lock_unix(\%dom); &obtain_lock_mail(\%dom); local (%taken, %utaken); &build_taken(\%taken, \%utaken); &foreign_require("mailboxes"); $mailboxes::no_permanent_index = 1; local %usermap; if ($got{'mail'}) { # Migrate mail users &cpanel_migrate_mailboxes($dom, \%dom, \%usermap); } # Move server owner's inbox file local $owner = &get_domain_owner(\%dom); if ($owner && !$parent) { &$first_print("Moving server owner's mailbox .."); local ($mfile, $mtype) = &user_mail_file($owner); local $srcfolder; if (-d "$homesrc/mail/cur" || -d "$homesrc/mail/new") { # Maildir format $srcfolder = { 'type' => 1, 'file' => "$homesrc/mail" }; } elsif (-r "$homesrc/mail/inbox") { # mbox format $srcfolder = { 'type' => 0, 'file' => "$homesrc/mail/inbox" }; } if ($srcfolder) { local $dstfolder = { 'type' => $mtype, 'file' => $mfile }; &mailboxes::mailbox_move_folder($srcfolder, $dstfolder); &set_mailfolder_owner($dstfolder, $owner); &mailboxes::mailbox_uncompress_folder($dstfolder) if (defined(&mailboxes::mailbox_uncompress_folder)); &$second_print(".. done"); } else { &$second_print(".. none exists"); } } # Build map from email addresses to users local %useremail; foreach my $uinfo (&list_domain_users(\%dom)) { if ($uinfo->{'email'}) { $useremail{$uinfo->{'email'}} = $uinfo; } } if ($got{'mail'}) { # Copy mail aliases local $acount = 0; local $domfwd; &$first_print("Copying email aliases .."); &set_alias_programs(); local %gotvirt = map { $_->{'from'}, $_ } &list_virtusers(); local $_; open(VAD, "<$userdir/vad/$dom"); while(<VAD>) { s/\r|\n//g; s/^\s*#.*$//; if (/^(\S+):\s*(\S+)$/) { # A domain forward exists .. local $virt = { 'from' => "\@$dom", 'to' => [ "%1\@$2" ] }; local $clash = $gotvirt{$virt->{'from'}}; &delete_virtuser($clash) if ($clash); &create_virtuser($virt); $acount++; $domfwd++; } } close(VAD); open(VA, "<$userdir/va/$dom"); while(<VA>) { s/\r|\n//g; s/^\s*#.*$//; if (/^(\S+):\s*(.*)$/) { local ($name, $v) = ($1, $2); next if (!$name); local @values; if ($v !~ /,/ && $v !~ /"/) { # A single destination, not quoted! @values = ( $v ); } else { # Comma-separated alias destinations while($v =~ /^\s*,?\s*"(\|)([^"]+)"(.*)$/ || $v =~ /^\s*,?\s*()"([^"]+)"(.*)$/ || $v =~ /^\s*,?\s*(\|)"([^"]+)"(.*)$/ || $v =~ /^\s*,?\s*()([^,\s]+)(.*)$/) { push(@values, $1.$2); $v = $3; } } local $mailman = 0; foreach my $v (@values) { if ($v =~ /:fail:\s+(.*)/) { # Fix bounce alias $v = "BOUNCE $1"; } local ($atype, $aname) = &alias_type($v, $name); if ($atype == 4 && $aname =~ /autorespond\s+(\S+)\@(\S+)\s+(\S+)/) { # Turn into Virtualmin auto-responder $v = "| $module_config_directory/autoreply.pl $3/$name $1"; &set_ownership_permissions( undef, undef, 0755, $3, "$3/$name"); } elsif ($atype == 4 && $aname =~ /mailman/) { $mailman++; } } # Don't create aliases for mailman lists next if ($mailman || $name =~ /^owner-/); # Already done a domain forward next if ($name =~ /^\*/ && $domfwd); # No need for a catchall that bounces mail, as this # will happen anyway next if ($name =~ /^\*/ && @values == 1 && $values[0] =~ /^BOUNCE/); if ($useremail{$name}) { # This is an alias from a user. Preserve # delivery to his mailbox though, as this is # what cPanel seems to do. local $uinfo = $useremail{$name}; local $olduinfo = { %$uinfo }; local $touser = $uinfo->{'user'}; if ($config{'mail_system'} == 0 && $escuser =~ /\@/) { $touser = &escape_replace_atsign_if_exists($touser); } $touser = "\\".$touser; $uinfo->{'to'} = [ $touser, @values ]; &modify_user($uinfo, $olduinfo, \%dom); } else { # Just create an alias if ($name !~ /\@/) { $name .= "\@".$dom; } local $virt = { 'from' => $name =~ /^\*/ ? "\@".$dom : $name, 'to' => \@values }; local $clash = $gotvirt{$virt->{'from'}}; &delete_virtuser($clash) if ($clash); &create_virtuser($virt); $acount++; } } } close(VA); &$second_print(".. done (migrated $acount aliases)"); } # Create mailing lists if ($got{'virtualmin-mailman'}) { local $lcount = 0; &$first_print("Re-creating mailing lists .."); foreach $ml (@lists) { local $err = &plugin_call("virtualmin-mailman", "create_list", $ml, $dom, "Migrated cPanel mailing list", undef, $dom{'emailto_addr'}, $dom{'pass'}); if ($err) { &$second_print("Failed to create $ml : $err"); } else { &execute_command("cp ".quotemeta("$userdir/mm/${ml}_${dom}/")."*.pck ".quotemeta("$virtualmin_mailman::mailman_var/lists/$ml")); $lcount++; } } &$second_print(".. done (created $lcount lists)"); } # Copy cron jobs for user (direct to his cron file) if (-r "$userdir/cron/$user" && !$waschild) { &foreign_require("cron"); &$first_print("Copying Cron jobs .."); $cron::cron_temp_file = &transname(); eval { local $main::error_must_die = 1; if ($parent) { # Append migrated cron to parent user's &cron::copy_cron_temp({ 'user' => $parent->{'user'} }); &execute_command( "cat $userdir/cron/$user >>$cron::cron_temp_file"); &cron::copy_crontab($parent->{'user'}); } else { # Just over-write cron &execute_command( "cp $userdir/cron/$user $cron::cron_temp_file"); &cron::copy_crontab($user); } }; if ($@) { &$second_print(".. failed : $@"); } else { &$second_print(".. done"); } } if ($got{'mysql'}) { # Re-create all MySQL databases local $mycount = 0; &$first_print("Re-creating and loading MySQL databases .."); &disable_quotas(\%dom); local $mydir = "$userdir/mysql"; local %dblist = map { $_, 1 } &get_cpanel_db_list("$userdir/mysql.sql", $user, $origuser); opendir(MYDIR, $mydir); while($myf = readdir(MYDIR)) { if ($myf =~ /^(\Q$user\E_\S*).sql$/ || $myf =~ /^(\Q$origuser\E_\S*).sql$/ || $myf =~ /^(\Q$user\E).sql$/ || $myf =~ /^(\Q$origuser\E).sql$/ || $myf =~ /^(\S+).sql$/ && $dblist{$1}) { local $db = $1; &$indent_print(); &create_mysql_database(\%dom, $db); &save_domain(\%dom, 1); local ($ex, $out) = &execute_dom_sql_file(\%dom, $db, "$mydir/$myf"); if ($ex) { &$first_print("Error loading $db : $out"); } &$outdent_print(); $mycount++; } } closedir(MYDIR); &enable_quotas(\%dom); &$second_print(".. done (created $mycount databases)"); # Re-create MySQL users if ($got{'mysql'}) { local $myucount = 0; &$first_print("Re-creating MySQL users .."); local %myusers; local $_; local (%donemysqluser, %donemysqlpriv); open(MYSQL, "<$userdir/mysql.sql"); while(<MYSQL>) { s/\r|\n//g; if (/^GRANT USAGE ON \*\.\* TO '(\S+)'\@'(\S+)' IDENTIFIED BY PASSWORD '(\S+)';/) { # Creating a MySQL user local ($myuser, $mypass) = ($1, $3); next if ($myuser eq $user); # domain owner next if ($donemysqluser{$myuser}++); local $myuinfo = &create_initial_user(\%dom); $myuinfo->{'user'} = $myuser; $myuinfo->{'pass'} = "x"; # not needed $myuinfo->{'mysql_pass'} = $mypass; $myuinfo->{'gid'} = $dom{'gid'}; $myuinfo->{'real'} = "MySQL user"; $myuinfo->{'home'} = "$dom{'home'}/$config{'homes_dir'}/$myuser"; $myuinfo->{'shell'} = $nologin_shell->{'shell'}; delete($myuinfo->{'email'}); $myusers{$myuser} = $myuinfo; } elsif (/GRANT ALL PRIVILEGES ON `(\S+)`\.\* TO '(\S+)'\@'(\S+)';/ || /GRANT SELECT.*\sON `(\S+)`\.\* TO '(\S+)'\@'(\S+)';/) { # Granting access to a MySQL database local ($mydb, $myuser) = ($1, $2); next if ($myuser eq $user); # domain owner next if ($donemysqlpriv{$mydb,$myuser}++); $mydb =~ s/\\(.)/$1/g; if ($myusers{$myuser}) { push(@{$myusers{$myuser}->{'dbs'}}, { 'type' => 'mysql', 'name' => $mydb }); } } } close(MYSQL); foreach my $myuinfo (values %myusers) { local $already = $usermap{$myuinfo->{'user'}}; if ($already) { # User already exists, so just give him the dbs local $olduinfo = { %$already }; $already->{'dbs'} = $myuinfo->{'dbs'}; &modify_user($already, $olduinfo, \%dom); } else { $myuinfo->{'uid'} = &allocate_uid(\%taken); &create_user_home($myuinfo, \%dom, 1); &create_user($myuinfo, \%dom); &create_mail_file($myuinfo, \%dom); $taken{$myuinfo->{'uid'}}++; $usermap{$myuinfo->{'user'}} = $myuinfo; } $myucount++; } &$second_print(".. done (created $myucount MySQL users)"); } } # Fix up FTP configuration if ($got{'ftp'}) { &$first_print("Modifying FTP server configuration .."); &require_proftpd(); local ($fvirt, $fconf, $conf, $anon, $aconf) = &get_proftpd_virtual($ipinfo->{'ip'}); if ($anon) { local $lref = &read_file_lines($anon->{'file'}); $lref->[$anon->{'line'}] = "<Anonymous $dom{'home'}/public_ftp>"; &flush_file_lines($anon->{'file'}); &$second_print(".. done"); ®ister_post_action(\&restart_proftpd); } else { &$second_print(".. could not find FTP server configuration"); } } # Migrate or update FTP users if (-r "$userdir/proftpdpasswd" && !$waschild) { local $fcount = 0; &$first_print("Re-creating FTP users .."); local $_; open(FTP, "<$userdir/proftpdpasswd"); while(<FTP>) { s/\r|\n//g; s/^\s*#.*$//; local ($fuser, $fpass, $fuid, $fgid, $fdummy, $fhome, $fshell) = split(/:/, $_); next if (!$fuser); $fuser = &remove_userdom($fuser, \%dom); next if ($fuser eq "ftp" || $fuser eq $user || $fuser eq $user."_logs"); # skip cpanel users local $fullfuser = &userdom_name(lc($fuser), \%dom); if ($fhome eq "/dev/null" || !&is_under_directory($dom{'home'}, $fhome)) { $fhome = "$dom{'home'}/$config{'homes_dir'}/$fuser"; } local $already = $usermap{$fuser} || $usermap{$fullfuser}; if ($already) { # Turn on FTP for existing user local $olduinfo = { %$already }; $already->{'shell'} = $ftp_shell->{'shell'}; &modify_user($already, $olduinfo, \%dom); } else { # Create new FTP-only user local $fuinfo = &create_initial_user(\%dom, 0, $fhome eq $ht || $fhome eq $dom{'home'}); $fuinfo->{'user'} = $fullfuser; $fuinfo->{'pass'} = $fpass; if ($fuinfo->{'webowner'}) { $fuinfo->{'uid'} = $dom{'uid'}; } else { $fuinfo->{'uid'} = &allocate_uid(\%taken); } $fuinfo->{'gid'} = $dom{'gid'}; $fuinfo->{'real'} = "FTP user"; $fuinfo->{'home'} = $fhome; $fuinfo->{'shell'} = $ftp_shell->{'shell'}; delete($fuinfo->{'email'}); $usermap{$fuser} = $fuinfo; if (!$user->{'nocreatehome'}) { &create_user_home($fuinfo, \%dom, 1); } &create_user($fuinfo, \%dom); if (!$user->{'nomailfile'}) { &create_mail_file($fuinfo, \%dom); } $taken{$fuinfo->{'uid'}}++; $fcount++; } } close(FTP); &$second_print(".. done (created $fcount FTP users)"); } &release_lock_unix(\%dom); &release_lock_mail(\%dom); # Migrate any parked domains as alias domains local @parked; if (!$waschild) { local $_; open(PARKED, "<$userdir/pds"); while(<PARKED>) { s/\r|\n//g; local ($pdom) = split(/\s+/, $_); push(@parked, $pdom) if ($pdom && $pdom !~ /^\*/); } close(PARKED); } # Create alias domain for sub-domain if ($aliasdom && $aliasdom !~ /^\*/) { push(@parked, $aliasdom); } # Actually create alias doms foreach my $pdom (&unique(@parked)) { if ($pdom eq $aliasdom) { &$first_print("Creating alias domain $pdom .."); } else { &$first_print("Creating parked domain $pdom .."); } if (&domain_name_clash($pdom)) { &$second_print(".. the domain $pdom already exists"); next; } &$indent_print(); local %alias = ( 'id', &domain_id(), 'dom', $pdom, 'user', $dom{'user'}, 'group', $dom{'group'}, 'prefix', $dom{'prefix'}, 'ugroup', $dom{'ugroup'}, 'pass', $dom{'pass'}, 'alias', $dom{'id'}, 'aliasmail', 1, 'uid', $dom{'uid'}, 'gid', $dom{'gid'}, 'ugid', $dom{'ugid'}, 'owner', $pdom eq $aliasdom ? "Migrated cPanel alias for $dom{'dom'}": "Parked domain for $dom{'dom'}", 'email', $dom{'email'}, 'name', 1, 'ip', $dom{'ip'}, 'virt', 0, 'source', $dom{'source'}, 'parent', $dom{'id'}, 'template', $dom{'template'}, 'reseller', $dom{'reseller'}, 'nocreationmail', 1, 'nocopyskel', 1, ); foreach my $f (@alias_features) { $alias{$f} = $dom{$f}; } local $parentdom = $dom{'parent'} ? &get_domain($dom{'parent'}) : \%dom; $alias{'home'} = &server_home_directory(\%alias, $parentdom); &generate_domain_password_hashes(\%alias, 1); &complete_domain(\%alias); &create_virtual_server(\%alias, $parentdom, $parentdom->{'user'}); if ($alias{'mail'}) { &cpanel_migrate_mailboxes($alias{'dom'}, \%alias, undef); } # Create parked domain aliases &$first_print("Copying email aliases for parked domain $pdom .."); my $acount = &cpanel_migrate_addon_aliases($pdom); &$second_print(".. done (migrated $acount aliases)"); &$outdent_print(); &$second_print($text{'setup_done'}); push(@rvdoms, \%alias); } # Read addons domain mapping file local %addons; local $lref = &read_file_lines("$userdir/addons"); foreach my $l (@$lref) { my ($a, $t) = split(/=/, $l); if ($a && $t) { $t =~ s/_/\./; $addons{$a} = $t; } } # Create sub-domains, silently skipping those for which no parent exists yet &create_sub_domains(1); # Create addon domains &create_addon_domains(); # Create sub-domains again, to catch those for which an addon target exists now &create_sub_domains(0); if ($got{'webalizer'}) { # Copy existing Weblizer stats to ~/public_html/stats &$first_print("Copying Weblizer data files .."); &execute_command("cp ". quotemeta($webalizer)."/*.{png,gif,html,current,hist} ". quotemeta(&webalizer_stats_dir(\%dom))); &execute_command("chown -R $dom{'uid'}:$dom{'ugid'} ". quotemeta(&webalizer_stats_dir(\%dom))); &$second_print($text{'setup_done'}); } if ($got{'virtualmin-awstats'}) { # Copy AWstats data files to ~/awstats &$first_print("Copying AWstats data files .."); &execute_command("cp ".quotemeta("$homesrc/tmp/awstats")."/*.$dom.txt ". quotemeta("$dom{'home'}/awstats")); &execute_command("chown -R $dom{'uid'}:$dom{'ugid'} ". quotemeta("$dom{'home'}/awstats")); &$second_print($text{'setup_done'}); } if ($parent) { # Re-save parent user, to update Webmin ACLs &refresh_webmin_user($parent); } &sync_alias_virtuals(\%dom); return @rvdoms; } # extract_cpanel_dir(file) # Extracts a tar.gz file, and returns a status code and either the directory # under which it was extracted, or an error message sub extract_cpanel_dir { local ($file) = @_; local $dir; if ($main::cpanel_dir_cache{$file} && -d $main::cpanel_dir_cache{$file}) { # Use cached extract from this session return (1, $main::cpanel_dir_cache{$file}); } if (!-e $file) { return (0, "File $file does not exist"); } elsif (-d $file) { # Already extracted $dir = $file; } else { $dir = &transname(); mkdir($dir, 0700); local $err = &extract_compressed_file($file, $dir); if ($err) { return (0, $err); } } $main::cpanel_dir_cache{$file} = $dir; return (1, $dir); } # extract_cpanel_file(file) # Extracts a .gz file, and returns the filename that is was extracted to sub extract_cpanel_file { return undef if (!-r $_[0]); local $temp = &transname(); local $qf = quotemeta($_[0]); local $out = `gunzip -c $qf >$temp`; return $? ? undef : $temp; } # read_cpanel_userdata_file(file, [offset]) # Converts a userdata file into a perl hash ref sub read_cpanel_userdata_file { local ($file, $pos) = @_; $pos ||= 0; local $lref = &read_file_lines($file, 1); local $startindent = 0; if ($lref->[$pos] =~ /^(\s+)/) { $startindent = length($1); } local %rv; local $lastname; while($pos < scalar(@$lref)) { local $indent = 0; if ($lref->[$pos] =~ /^(\s+)/) { $indent = length($1); } if ($indent < $startindent) { # End of this section last; } elsif ($indent > $startindent) { # Start of a new section if ($lref->[$pos] =~ /^\s*\-/) { # Element in an array $rv{$lastname} ||= [ ]; local ($subrv, $subpos) = &read_cpanel_userdata_file($file, $pos+1); push(@{$rv{$lastname}}, $subrv); $pos = $subpos - 1; } else { # Start of a section local ($subrv, $subpos) = &read_cpanel_userdata_file($file, $pos); $rv{$lastname} = $subrv; $pos = $subpos - 1; } } elsif ($lref->[$pos] =~ /^\s*(\S+):\s*(.*)/) { # A value in this section $rv{$1} = $2; $lastname = $1; } $pos++; } return wantarray ? ( \%rv, $pos ) : \%rv; } sub create_addon_domains { local ($skip_missing_target) = @_; # Create addon domains as alias domains opendir(VF, "$userdir/vf"); foreach my $vf (readdir(VF)) { local ($clash) = grep { $_->{'dom'} eq $vf } @rvdoms; next if ($clash); next if ($vf eq "." || $vf eq ".." || $clash); next if (!$addons{$vf}); local $target = &get_domain_by("dom", $addons{$vf}); next if (!$target && $skip_missing_target); &$first_print("Creating addon domain $vf .."); if (!$target) { &$second_print(".. skipping, as target $addons{$vf} does not exist"); next; } if (&domain_name_clash($vf)) { &$second_print(".. the domain $vf already exists"); next; } &$indent_print(); local %alias = ( 'id', &domain_id(), 'dom', $vf, 'user', $dom{'user'}, 'group', $dom{'group'}, 'prefix', $dom{'prefix'}, 'ugroup', $dom{'ugroup'}, 'pass', $dom{'pass'}, 'alias', $target->{'id'}, 'aliasmail', 1, 'uid', $dom{'uid'}, 'gid', $dom{'gid'}, 'ugid', $dom{'ugid'}, 'owner', "Migrated cPanel alias for $target->{'dom'}", 'email', $dom{'email'}, 'name', 1, 'ip', $target->{'ip'}, 'virt', 0, 'source', $dom{'source'}, 'parent', $dom{'id'}, 'template', $target->{'template'}, 'reseller', $target->{'reseller'}, 'nocreationmail', 1, 'nocopyskel', 1, ); foreach my $f (@alias_features) { $alias{$f} = $target->{$f}; } local $parentdom = $dom{'parent'} ? &get_domain($dom{'parent'}) : \%dom; $alias{'home'} = &server_home_directory(\%alias, $parentdom); &generate_domain_password_hashes(\%alias, 1); &complete_domain(\%alias); &create_virtual_server(\%alias, $parentdom, $parentdom->{'user'}); if ($alias{'mail'}) { &cpanel_migrate_mailboxes($alias{'dom'}, \%alias, undef); } &$outdent_print(); &$second_print($text{'setup_done'}); push(@rvdoms, \%alias); # Create parked domain aliases &$first_print("Copying email aliases for addon domain $vf .."); my $acount = &cpanel_migrate_addon_aliases($vf); &$second_print(".. done (migrated $acount aliases)"); } } sub create_sub_domains { local ($skip_missing_target) = @_; # Create sub-domains as virtualmin sub-domains, from vf directory opendir(VF, "$userdir/vf"); foreach my $vf (readdir(VF)) { local ($clash) = grep { $_->{'dom'} eq $vf } @rvdoms; next if ($vf eq "." || $vf eq ".." || $clash); next if ($addons{$vf}); local (%subof, $subprefix); foreach my $rv (grep { !$_->{'subdom'} } @rvdoms) { if ($vf =~ /^(\S+)\.\Q$rv->{'dom'}\E$/) { $subprefix = $1; %subof = %$rv; last; } } if ((!%subof || !$subof{'dom'}) && $skip_missing_target) { # Skip silently next; } if (!%subof || !$subof{'dom'}) { &$first_print("Creating sub-domain $vf .."); &$second_print(".. skipping, as not a sub-domain of $dom or any other migrated domain"); next; } if (&domain_name_clash($vf)) { &$first_print("Creating sub-domain $vf .."); &$second_print(".. the domain $vf already exists"); next; } elsif ($subof{'alias'}) { # Sub-domain of an alias ... need to create as a sub-server # of the main domain &$first_print("Creating sub-server sub-domain $vf .."); &$indent_print(); local %subs = ( 'id', &domain_id(), 'dom', $vf, 'user', $dom{'user'}, 'group', $dom{'group'}, 'prefix', $dom{'prefix'}, 'ugroup', $dom{'ugroup'}, 'pass', $dom{'pass'}, 'uid', $dom{'uid'}, 'gid', $dom{'gid'}, 'ugid', $dom{'ugid'}, 'owner', "Migrated cPanel sub-server", 'email', $dom{'email'}, 'name', 1, 'ip', $dom{'ip'}, 'virt', 0, 'source', $dom{'source'}, 'parent', $dom{'id'}, 'template', $dom{'template'}, 'reseller', $dom{'reseller'}, 'nocreationmail', 1, 'nocopyskel', 1, ); foreach my $f (@subdom_features) { if ($f ne "unix" && $f ne "webmin") { $subs{$f} = $dom{$f}; } } local $parentdom = $dom{'parent'} ? &get_domain($dom{'parent'}) : \%dom; $subs{'home'} = &server_home_directory(\%subs, $parentdom); &generate_domain_password_hashes(\%subs, 1); &complete_domain(\%subs); &create_virtual_server(\%subs, $parentdom, $parentdom->{'user'}); # Copy files from parent local $sdsrc = "$ht/$subprefix"; local $qsdsrc = quotemeta($sdsrc); local $sddst = &public_html_dir(\%subs); local $qsddst = quotemeta($sddst); local $out; if (-d $sdsrc) { &$first_print( "Copying web pages from $sdsrc to $sddst .."); &execute_command("cd $qsdsrc && ". "(".&make_tar_command("cf", "-", "."). " | (cd $qsddst && ". &make_tar_command("xf", "-")."))", undef, \$out, \$out); if ($?) { &$second_print(".. copy failed :<tt>$out</tt>"); } else { &$second_print(".. done"); } &set_home_ownership(\%subs); } &$outdent_print(); &$second_print($text{'setup_done'}); push(@rvdoms, \%subs); } else { # Sub-domain of a regular domain &$first_print("Creating sub-domain $vf .."); &$indent_print(); local %subd = ( 'id', &domain_id(), 'dom', $vf, 'user', $dom{'user'}, 'group', $dom{'group'}, 'prefix', $dom{'prefix'}, 'ugroup', $dom{'ugroup'}, 'pass', $dom{'pass'}, 'subdom', $subof{'id'}, 'subprefix', $subprefix, 'uid', $dom{'uid'}, 'gid', $dom{'gid'}, 'ugid', $dom{'ugid'}, 'owner', "Migrated cPanel sub-domain", 'email', $dom{'email'}, 'name', 1, 'ip', $dom{'ip'}, 'virt', 0, 'source', $dom{'source'}, 'parent', $dom{'id'}, 'template', $dom{'template'}, 'reseller', $dom{'reseller'}, 'nocreationmail', 1, 'nocopyskel', 1, 'no_tmpl_aliases', 1, ); $subd{'mail'} = 0; foreach my $f (@subdom_features) { if ($f eq 'mail') { $subd{$f} = $subof{$f} && -r "$userdir/va/$vf"; } elsif ($f eq 'ssl') { # Off for sub-domains, for now $subd{$f} = 0; } else { $subd{$f} = $subof{$f}; } } local $parentdom = $dom{'parent'} ? &get_domain($dom{'parent'}) : \%dom; $subd{'home'} = &server_home_directory(\%subd, $parentdom); &generate_domain_password_hashes(\%subd, 1); &complete_domain(\%subd); # Extract correct sub-domain root dir local $userdata = &read_cpanel_userdata_file( "$userdir/userdata/$vf"); if ($userdata->{'documentroot'} =~ /^\/home\/([^\/]+)\/public_html\/(.*)/) { $subd{'public_html_dir'} = "../../$subof{'public_html_dir'}/$2"; $subd{'public_html_path'} = "$subof{'public_html_path'}/$2"; } # Set cgi directories to cpanel standard $subd{'cgi_bin_dir'} = "../../$subof{'public_html_dir'}/$subprefix/cgi-bin"; $subd{'cgi_bin_path'} = "$subof{'public_html_path'}/$subprefix/cgi-bin"; &create_virtual_server(\%subd, $parentdom, $parentdom->{'user'}); &create_standard_directory_for_domain( \%subd, $subd{'cgi_bin_path'}, $tmpl->{'web_html_perms'}); # Cpanel sub-domains always seem to forward mail to the parent if ($subd{'mail'}) { local $virt = { 'from' => "\@$vf", 'to' => [ "%1\@".$subof{'dom'} ] }; &create_virtuser($virt); } &$outdent_print(); &$second_print($text{'setup_done'}); push(@rvdoms, \%subd); } } closedir(VF); } # cpanel_migrate_mailboxes(domain-name, &domain, &user-map) # Re-create mailbox users from a cPanel backup sub cpanel_migrate_mailboxes { local ($dom, $d, $usermap) = @_; &foreign_require("mailboxes"); &$first_print("Re-creating mail users for $dom .."); local $mcount = 0; local (%pass, %quota); local $_; open(SHADOW, "<$homesrc/etc/$dom/shadow"); while(<SHADOW>) { s/\r|\n//g; local ($suser, $spass) = split(/:/, $_); $pass{$suser} = $spass; } close(SHADOW); local $_; local $bsize = "a_bsize("home"); open(QUOTA, "<$homesrc/etc/$dom/quota"); while(<QUOTA>) { s/\r|\n//g; local ($quser, $qquota) = split(/:/, $_); $quota{$quser} = $bsize ? int($qquota/$bsize) : 0; } close(QUOTA); local $_; open(PASSWD, "<$homesrc/etc/$dom/passwd"); while(<PASSWD>) { # Create the user s/\r|\n//g; local ($muser, $mdummy, $muid, $mgid, $mreal, $mdir, $mshell) = split(/:/, $_); next if (!$muser); $muser = &remove_userdom($muser, $d); next if ($muser =~ /_logs$/); # Special logs user next if ($muser eq $user && !$parent); # Domain owner local $uinfo = &create_initial_user($d); $uinfo->{'user'} = &userdom_name(lc($muser), $d); $uinfo->{'pass'} = $pass{$muser}; $uinfo->{'uid'} = &allocate_uid(\%taken); $uinfo->{'gid'} = $d->{'gid'}; $uinfo->{'real'} = $mreal; $uinfo->{'home'} = "$d->{'home'}/$config{'homes_dir'}/". lc($muser); $uinfo->{'shell'} = $nologin_shell->{'shell'}; $uinfo->{'email'} = lc($muser)."\@$dom"; $uinfo->{'qquota'} = $quota{$muser}; $uinfo->{'quota'} = $quota{$muser}; $uinfo->{'mquota'} = $quota{$muser}; &create_user_home($uinfo, $d, 1); &create_user($uinfo, $d); $taken{$uinfo->{'uid'}}++; local ($crfile, $crtype) = &create_mail_file($uinfo, $d); # Move his mail files local $mailsrc = "$homesrc/mail/$dom/$muser"; local $sfdir = $mailboxes::config{'mail_usermin'}; local $sftype = $sfdir eq 'Maildir' ? 1 : 0; local $sfpath = "$uinfo->{'home'}/$sfdir"; if (!-d $sfpath && !$sftype) { # Create ~/mail if needed &make_dir($sfpath, 0755); &set_ownership_permissions( $uinfo->{'uid'}, $uinfo->{'gid'}, undef, $sfpath); } if (-d "$mailsrc/cur" || -d "$mailsrc/new") { # Mail directory is in Maildir format, and sub-folders # are in Maildir++ local $srcfolder = { 'type' => 1, 'file' => $mailsrc }; local $dstfolder = { 'file' => $crfile, 'type' => $crtype }; &mailboxes::mailbox_move_folder($srcfolder, $dstfolder); &set_mailfolder_owner($dstfolder, $uinfo); &mailboxes::mailbox_uncompress_folder($dstfolder) if (defined(&mailboxes::mailbox_uncompress_folder)); opendir(DIR, $mailsrc); while(my $mf = readdir(DIR)) { next if ($mf eq "." || $mf eq ".." || $mf !~ /^\./); local $srcfolder = { 'type' => 1, 'file' => "$mailsrc/$mf" }; # Remove . if destination is not Maildir++ $mf =~ s/^\.// if (!$sftype); local $dstfolder = { 'type' => $sftype, 'file' => "$sfpath/$mf" }; &mailboxes::mailbox_move_folder($srcfolder, $dstfolder); &set_mailfolder_owner($dstfolder, $uinfo); &mailboxes::mailbox_uncompress_folder($dstfolder) if (defined(&mailboxes::mailbox_uncompress_folder)); } closedir(DIR); } elsif (-d "$mailsrc/storage") { # Mail directory is in mdbox format .. convert to mbox then move local $mdtemp = &transname(); ©_source_dest($mailsrc, $mdtemp); local $temp = &transname(); &make_dir($temp, 0755); my $err; &execute_command("chown -R ".quotemeta($uinfo->{'user'}).": ".quotemeta($mdtemp)." ".quotemeta($temp), undef, \$err, \$err); local $out = &backquote_command("dsync -u ".quotemeta($uinfo->{'user'})." -o \"mail_location=mdbox:$mdtemp\" backup mbox:".quotemeta($temp)." 2>&1"); &unlink_file($mdtemp); opendir(DIR, $temp); while(my $mf = readdir(DIR)) { next if ($mf =~ /^\./); local $srcfolder = { 'type' => 0, 'file' => "$temp/$mf" }; local $dstfolder; if ($mf eq "inbox") { $dstfolder = { 'file' => $crfile, 'type' => $crtype }; } else { # Copying an extra folder - use # Maildir++ name if dest folders are # under ~/Maildir $mf = ".$mf" if ($sftype); $dstfolder = { 'type' => $sftype, 'file' => "$sfpath/$mf" }; } &mailboxes::mailbox_move_folder($srcfolder, $dstfolder); &set_mailfolder_owner($dstfolder, $uinfo); } closedir(DIR); &unlink_file($temp); } elsif (!-d $mailsrc) { # Assume that mail files are mbox formatted opendir(DIR, $mailsrc); while(my $mf = readdir(DIR)) { next if ($mf =~ /^\./); local $srcfolder = { 'type' => 0, 'file' => "$mailsrc/$mf" }; local $dstfolder; if ($mf eq "inbox") { $dstfolder = { 'file' => $crfile, 'type' => $crtype }; } else { # Copying an extra folder - use # Maildir++ name if dest folders are # under ~/Maildir $mf = ".$mf" if ($sftype); $dstfolder = { 'type' => $sftype, 'file' => "$sfpath/$mf" }; } &mailboxes::mailbox_move_folder($srcfolder, $dstfolder); &set_mailfolder_owner($dstfolder, $uinfo); } closedir(DIR); } $mcount++; if ($usermap) { $usermap->{$muser} = $uinfo; } } close(PASSWD); &$second_print(".. done (migrated $mcount mail users)"); } # cpanel_migrate_addon_aliases(domain) sub cpanel_migrate_addon_aliases { local ($vf) = @_; local $acount = 0; local %gotvirt = map { $_->{'from'}, $_ } &list_virtusers(); open(VA, "<$userdir/va/$vf"); while(<VA>) { s/\r|\n//g; s/^\s*#.*$//; if (/^(\S+):\s*(.*)$/) { local ($name, $v) = ($1, $2); next if (!$name); local @values; if ($v !~ /,/ && $v !~ /"/) { # A single destination, not quoted! @values = ( $v ); } else { # Comma-separated alias destinations while($v =~ /^\s*,?\s*"(\|)([^"]+)"(.*)$/ || $v =~ /^\s*,?\s*()"([^"]+)"(.*)$/ || $v =~ /^\s*,?\s*(\|)"([^"]+)"(.*)$/ || $v =~ /^\s*,?\s*()([^,\s]+)(.*)$/) { push(@values, $1.$2); $v = $3; } } local $mailman = 0; foreach my $v (@values) { if ($v =~ /:fail:\s+(.*)/) { # Fix bounce alias $v = "BOUNCE $1"; } local ($atype, $aname) = &alias_type($v, $name); if ($atype == 4 && $aname =~ /autorespond\s+(\S+)\@(\S+)\s+(\S+)/) { # Turn into Virtualmin auto-responder $v = "| $module_config_directory/autoreply.pl $3/$name $1"; &set_ownership_permissions( undef, undef, 0755, $3, "$3/$name"); } elsif ($atype == 4 && $aname =~ /mailman/) { $mailman++; } } # Don't create aliases for mailman lists next if ($mailman || $name =~ /^owner-/); # Already done a domain forward next if ($name =~ /^\*/); # Just create an alias if ($name !~ /\@/) { $name .= "\@".$vf; } local $virt = { 'from' => $name =~ /^\*/ ? "\@".$vf : $name, 'to' => \@values }; local $clash = $gotvirt{$virt->{'from'}}; &delete_virtuser($clash) if ($clash); &create_virtuser($virt); $acount++; } } close(VA); return $acount; } # get_cpanel_db_list(file, user, origuser) # Reads from mysql.sql the list of DBs granted to the domain user sub get_cpanel_db_list { my ($file, $user1, $user2) = @_; my $lref = &read_file_lines($file, 1); my @rv; foreach my $l (@$lref) { if ($l =~ /^GRANT ALL PRIVILEGES ON `([^`]+)`\.\* TO '([^']+)'/ && ($2 eq $user1 || $2 eq $user2)) { my $db = $1; $db =~ s/\\(.)/$1/g; push(@rv, $db); } } return @rv; } 1;Private