php IHDR w Q )Ba pHYs sRGB gAMA a IDATxMk\U s&uo,mD )Xw+e?tw.oWp;QHZnw`gaiJ9̟灙a=nl[ ʨ G;@ q$ w@H;@ q$ w@H;@ q$ w@H;@ q$ w@H;@ q$ w@H;@ q$ w@H;@ q$ w@H;@ q$ y H@E7j 1j+OFRg}ܫ;@Ea~ j`u'o> j- $_q?qS XzG'ay
files >> /usr/libexec/webmin/virtualmin-svn/ |
files >> //usr/libexec/webmin/virtualmin-svn/virtual_feature.pl |
# Defines functions for this feature do 'virtualmin-svn-lib.pl'; $input_name = $module_name; $input_name =~ s/[^A-Za-z0-9]/_/g; &load_theme_library(); # feature_name() # Returns a short name for this feature sub feature_name { return $text{'feat_name'}; } # feature_losing(&domain) # Returns a description of what will be deleted when this feature is removed sub feature_losing { return $text{'feat_losing'}; } # feature_disname(&domain) # Returns a description of what will be turned off when this feature is disabled sub feature_disname { return $text{'feat_disname'}; } # feature_label(in-edit-form) # Returns the name of this feature, as displayed on the domain creation and # editing form sub feature_label { local ($edit) = @_; return $edit ? $text{'feat_label2'} : $text{'feat_label'}; } sub feature_hlink { return "label"; } # feature_check() # Returns undef if all the needed programs for this feature are installed, # or an error message if not sub feature_check { local $err = &svn_check(); if (!$err) { # Check for htdigest command if ($config{'auth'} eq 'Digest') { &foreign_require("htaccess-htpasswd", "htaccess-lib.pl"); if (!$htaccess_htpasswd::htdigest_command) { $err = &text('feat_edigest', "<tt>htdigest</tt>"); } } } return $err; } # feature_depends(&domain) # Returns undef if all pre-requisite features for this domain are enabled, # or an error message if not sub feature_depends { return $_[0]->{'web'} ? undef : $text{'feat_edepweb'}; } # feature_clash(&domain) # Returns undef if there is no clash for this domain for this feature, or # an error message if so sub feature_clash { return undef; } # feature_suitable([&parentdom], [&aliasdom], [&subdom]) # Returns 1 if some feature can be used with the specified alias and # parent domains sub feature_suitable { return $_[1] || $_[2] ? 0 : 1; # not for alias domains } # feature_setup(&domain) # Called when this feature is added, with the domain object as a parameter sub feature_setup { &$virtual_server::first_print($text{'setup_dav'}); &virtual_server::obtain_lock_web($_[0]); local $any; $any++ if (&add_svn_directives($_[0], $_[0]->{'web_port'})); $any++ if ($_[0]->{'ssl'} && &add_svn_directives($_[0], $_[0]->{'web_sslport'})); if (!$any) { &$virtual_server::second_print( $virtual_server::text{'delete_noapache'}); } else { # Create needed directories ~/etc/ and ~/svn local $passwd_file = &passwd_file($_[0]); local $conf_file = &conf_file($_[0]); if (!-d "$_[0]->{'home'}/svn") { &virtual_server::make_dir_as_domain_user( $_[0], "$_[0]->{'home'}/svn", 02755); } if (!-d "$_[0]->{'home'}/etc") { &virtual_server::make_dir_as_domain_user( $_[0], "$_[0]->{'home'}/etc", 0755); } # Create password and configuration files if (!-r $passwd_file) { &lock_file($passwd_file); &virtual_server::open_tempfile_as_domain_user( $_[0], PASSWD, ">$passwd_file", 0, 1); &virtual_server::close_tempfile_as_domain_user( $_[0], PASSWD); &virtual_server::set_permissions_as_domain_user( $_[0], 0755, $passwd_file); &unlock_file($passwd_file); } if (!-r $conf_file) { &lock_file($conf_file); &virtual_server::open_tempfile_as_domain_user( $_[0], PASSWD, ">$conf_file", 0, 1); &virtual_server::close_tempfile_as_domain_user( $_[0], PASSWD); &virtual_server::set_permissions_as_domain_user( $_[0], 0755, $conf_file); &unlock_file($conf_file); } &$virtual_server::second_print($virtual_server::text{'setup_done'}); &virtual_server::register_post_action(\&virtual_server::restart_apache); # Grant access to the domain's owner my $uinfo; if (!$_[0]->{'parent'} && ($uinfo = &virtual_server::get_domain_owner($_[0]))) { &$virtual_server::first_print($text{'setup_svnuser'}); &foreign_require("htaccess-htpasswd", "htaccess-lib.pl"); local $un = &virtual_server::remove_userdom( $uinfo->{'user'}, $_[0]); local $newuser = { 'user' => $un, 'enabled' => 1 }; if ($config{'auth'} eq 'Digest') { # Do Digest encryption $newuser->{'digest'} = 1; $newuser->{'pass'} = $uinfo->{'digest_enc_pass'} || &htaccess_htpasswd::digest_password ($un, $_[0]->{'dom'}, $_[0]->{'pass'}); } else { # Copy Unix crypted pass $newuser->{'pass'} = $uinfo->{'pass'}; } &virtual_server::write_as_domain_user($_[0], sub { &htaccess_htpasswd::create_user( $newuser, $passwd_file) }); &$virtual_server::second_print( $virtual_server::text{'setup_done'}); } } # Set default limit from template if (!exists($_[0]->{$module_name."limit"})) { local $tmpl = &virtual_server::get_template($_[0]->{'template'}); $_[0]->{$module_name."limit"} = $tmpl->{$module_name."limit"} eq "none" ? "" : $tmpl->{$module_name."limit"}; } # Make sure /svn isn't proxied if (defined(&virtual_server::setup_noproxy_path)) { &virtual_server::setup_noproxy_path( $_[0], { }, undef, { 'path' => '/svn/' }, 1); } &virtual_server::release_lock_web($_[0]); } sub add_svn_directives { local ($d, $port) = @_; local ($virt, $vconf) = &virtual_server::get_apache_virtual($d->{'dom'}, $port); if ($virt) { local $lref = &read_file_lines($virt->{'file'}); local ($locstart, $locend) = &find_svn_lines($lref, $virt->{'line'}, $virt->{'eline'}); local @lines; local $passwd_file = &passwd_file($d); local $conf_file = &conf_file($d); local $at = $config{'auth'}; local $auf = $at eq "Digest" && $apache::httpd_modules{'core'} < 2.2 ? "AuthDigestFile" : "AuthUserFile"; local @adp = $at eq "Digest" && $apache::httpd_modules{'core'} >= 2.2 ? ("AuthDigestProvider file") : ( ); local @auto; @auto = ( "SVNAutoversioning on") if ($config{'auto'}); local @norewrite; if ($apache::httpd_modules{'mod_rewrite'}) { @norewrite = ( "RewriteEngine off" ); } if (!$locstart) { push(@lines, "<Location /svn>", "DAV svn", @auto, "SVNParentPath $d->{'home'}/svn", "AuthType $at", "AuthName $d->{'dom'}", "$auf $passwd_file", @adp, "Require valid-user", "AuthzSVNAccessFile $conf_file", "Satisfy Any", @norewrite, "ErrorDocument 404 default", "</Location>"); } splice(@$lref, $virt->{'eline'}, 0, @lines); &flush_file_lines(); undef(@apache::get_config_cache); return 1; } else { return 0; } } # feature_modify(&domain, &olddomain) # Called when a domain with this feature is modified sub feature_modify { if ($_[0]->{'dom'} ne $_[1]->{'dom'}) { # Change AuthName in webserver &$virtual_server::first_print($text{'save_dav'}); &virtual_server::obtain_lock_web($_[0]); &change_svn_directives($_[0], $_[0]->{'web_port'}); &change_svn_directives($_[0], $_[0]->{'web_sslport'}) if ($_[0]->{'ssl'}); &virtual_server::release_lock_web($_[0]); &$virtual_server::second_print($virtual_server::text{'setup_done'}); } if ($_[0]->{'pass_set'}) { # Change password for domain admin, if he has an SVN account local @users = &list_users($_[0]); local ($suser) = grep { $_->{'user'} eq $_[0]->{'user'} } @users; if ($suser) { &$virtual_server::first_print($text{'save_davpass'}); &lock_file(&passwd_file($_[0])); &lock_file(&conf_file($_[0])); if ($config{'auth'} eq 'Digest') { $suser->{'pass'} = $_[0]->{'digest_enc_pass'} || &htaccess_htpasswd::digest_password( $_[0]->{'user'}, $_[0]->{'dom'}, $_[0]->{'pass'}); } else { $suser->{'pass'} = $_[0]->{'crypt_enc_pass'} || &htaccess_htpasswd::encrypt_password( $_[0]->{'pass'}); } &virtual_server::write_as_domain_user($_[0], sub { &htaccess_htpasswd::modify_user($suser) }); &unlock_file(&passwd_file($_[0])); &unlock_file(&conf_file($_[0])); &$virtual_server::second_print( $virtual_server::text{'setup_done'}); } } } sub change_svn_directives { local ($d, $port) = @_; local $conf = &apache::get_config(); local ($virt, $vconf) = &virtual_server::get_apache_virtual($d->{'dom'}, $port); return 0 if (!$virt); local @locs = &apache::find_directive_struct("Location", $vconf); local ($davloc) = grep { $_->{'words'}->[0] eq "/svn" } @locs; if ($davloc) { local $auth = &apache::find_directive_struct( "AuthName", $davloc->{'members'}); if ($auth) { &apache::save_directive("AuthName", [ $d->{'dom'} ], $davloc->{'members'}, $conf); &flush_file_lines(); } return 1; } return 0; } # feature_delete(&domain) # Called when this feature is disabled, or when the domain is being deleted sub feature_delete { &$virtual_server::first_print($text{'delete_dav'}); &virtual_server::obtain_lock_web($_[0]); local $any; $any++ if (&remove_svn_directives($_[0], $_[0]->{'web_port'})); $any++ if ($_[0]->{'ssl'} && &remove_svn_directives($_[0], $_[0]->{'web_sslport'})); &virtual_server::release_lock_web($_[0]); if (!$any) { &$virtual_server::second_print( $virtual_server::text{'delete_noapache'}); } else { &$virtual_server::second_print($virtual_server::text{'setup_done'}); &virtual_server::register_post_action(\&virtual_server::restart_apache); # Remove negative proxy for /svn if (defined(&virtual_server::delete_noproxy_path)) { &virtual_server::delete_noproxy_path( $_[0], { }, undef, { 'path' => '/svn/' }); } } } sub remove_svn_directives { local ($d, $port) = @_; local ($virt, $vconf) = &virtual_server::get_apache_virtual($d->{'dom'}, $port); if ($virt) { local $lref = &read_file_lines($virt->{'file'}); local ($locstart, $locend) = &find_svn_lines($lref, $virt->{'line'}, $virt->{'eline'}); if ($locstart) { splice(@$lref, $locstart, $locend-$locstart+1); } &flush_file_lines(); undef(@apache::get_config_cache); return 1; } else { return 0; } } # find_svn_lines(&lref, start, end) sub find_svn_lines { local ($locstart, $locend, $i); for($i=$_[1]; $i<=$_[2]; $i++) { if ($_[0]->[$i] =~ /^\s*<Location\s+\/svn>/i && !$locstart) { $locstart = $i; } elsif ($_[0]->[$i] =~ /^\s*<\/Location>/i && $locstart && !$locend) { $locend = $i; } } return ($locstart, $locend); } # feature_webmin(&domain) # Returns a list of webmin module names and ACL hash references to be set for # the Webmin user when this feature is enabled sub feature_webmin { local @doms = map { $_->{'dom'} } grep { $_->{$module_name} } @{$_[1]}; if (@doms) { return ( [ $module_name, { 'dom' => join(" ", @doms), 'max' => $_[0]->{$module_name.'limit'}, 'noconfig' => 1 } ] ); } else { return ( ); } } # feature_limits_input(&domain) # Returns HTML for editing limits related to this plugin sub feature_limits_input { local ($d) = @_; return undef if (!$d->{$module_name}); return &ui_table_row(&hlink($text{'limits_max'}, "limits_max"), &ui_opt_textbox($input_name."limit", $d->{$module_name."limit"}, 4, $virtual_server::text{'form_unlimit'}, $virtual_server::text{'form_atmost'})); } # feature_limits_parse(&domain, &in) # Updates the domain with limit inputs generated by feature_limits_input sub feature_limits_parse { local ($d, $in) = @_; return undef if (!$d->{$module_name}); if ($in->{$input_name."limit_def"}) { delete($d->{$module_name."limit"}); } else { $in->{$input_name."limit"} =~ /^\d+$/ || return $text{'limit_emax'}; $d->{$module_name."limit"} = $in->{$input_name."limit"}; } return undef; } # feature_links(&domain) # Returns an array of link objects for webmin modules for this feature sub feature_links { local ($d) = @_; return ( { 'mod' => $module_name, 'desc' => $text{'links_link'}, 'page' => 'index.cgi?show='.$d->{'dom'}, 'cat' => 'services', } ); } sub feature_modules { return ( [ $module_name, $text{'feat_module'} ] ); } # feature_backup(&domain, file, &opts, &all-opts) # Copy the SVN password file, config file and repositories for the domain sub feature_backup { local ($d, $file, $opts) = @_; &$virtual_server::first_print($text{'feat_backup'}); # Copy actual repositories local $tar = &virtual_server::get_tar_command(); local $temp = &transname(); local $out = &backquote_command("cd ".quotemeta("$d->{'home'}/svn")." && ". "$tar cf ".quotemeta($temp)." . 2>&1"); if ($?) { &$virtual_server::second_print(&text('feat_tar', "<pre>$out</pre>")); return 0; } &virtual_server::copy_write_as_domain_user($d, $temp, $file); &unlink_file($temp); # Copy users file local $pfile = &passwd_file($_[0]); if (!-r $pfile) { &$virtual_server::second_print($text{'feat_nopfile'}); return 0; } &virtual_server::copy_write_as_domain_user($d, $pfile, $file."_users"); # Copy config file local $cfile = &conf_file($_[0]); if (!-r $cfile) { &$virtual_server::second_print($text{'feat_nopfile'}); return 0; } &virtual_server::copy_write_as_domain_user($d, $cfile, $file."_config"); &$virtual_server::second_print($virtual_server::text{'setup_done'}); return 1; } # feature_restore(&domain, file, &opts, &all-opts) # Called to restore this feature for the domain from the given file sub feature_restore { local ($d, $file, $opts) = @_; &$virtual_server::first_print($text{'feat_restore'}); # Extract tar file of repositories (deleting old ones first) local $tar = &virtual_server::get_tar_command(); &execute_command("rm -rf ".quotemeta("$d->{'home'}/svn")."/*"); local ($out, $ex) = &virtual_server::run_as_domain_user($d, "cd ".quotemeta("$d->{'home'}/svn")." && $tar xf ".quotemeta($file)." 2>&1"); if ($ex) { &$virtual_server::second_print(&text('feat_untar', "<pre>$out</pre>")); return 0; } # Copy users file local $pfile = &passwd_file($d); local ($ok, $out) = &virtual_server::copy_source_dest_as_domain_user( $d, $file."_users", $pfile); if (!$ok) { &$virtual_server::second_print(&text('feat_copypfile2', $out)); return 0; } # Copy config file local $cfile = &conf_file($d); ($ok, $out) = &virtual_server::copy_source_dest_as_domain_user( $d, $file."_config", $cfile); if (!$ok) { &$virtual_server::second_print(&text('feat_copycfile2', $out)); return 0; } # Fix repo permissions foreach my $rep (&list_reps($d)) { &set_rep_permissions($dom, $rep); } &$virtual_server::second_print($virtual_server::text{'setup_done'}); return 1; } sub feature_backup_name { return $text{'feat_backup_name'}; } # feature_validate(&domain) # Checks if this feature is properly setup for the virtual server, and returns # an error message if any problem is found sub feature_validate { local ($d) = @_; local $passwd_file = &passwd_file($d); -r $passwd_file || return &text('feat_evalidatefile', "<tt>$passwd_file</tt>"); local $conf_file = &conf_file($d); -r $conf_file || return &text('feat_evalidateconf', "<tt>$conf_file</tt>"); local ($virt, $vconf) = &virtual_server::get_apache_virtual($d->{'dom'}, $port); $virt || return &virtual_server::text('validate_eweb', $d->{'dom'}); local $lref = &read_file_lines($virt->{'file'}); local ($locstart, $locend) = &find_svn_lines($lref, $virt->{'line'}, $virt->{'eline'}); $locstart || return &text('feat_evalidateloc'); return undef; } # mailbox_inputs(&user, new, &domain) # Returns HTML for additional inputs on the mailbox form. These should be # formatted to appear inside a table. sub mailbox_inputs { local ($user, $new, $dom) = @_; return undef if (!$dom || !$dom->{$module_name}); local $un = &virtual_server::remove_userdom($user->{'user'}, $dom); local $suser; if (!$new) { local @users = &list_users($dom); ($suser) = grep { $_->{'user'} eq $un } @users; } local $main::ui_table_cols = 2; local @reps = &list_reps($dom); local (@rwreps, @roreps); foreach $r (@reps) { local @rusers = &list_rep_users($dom, $r->{'rep'}); local ($ruser) = grep { $_->{'user'} eq $un } @rusers; if ($ruser && $ruser->{'perms'} eq 'rw') { push(@rwreps, $r->{'rep'}); } elsif ($ruser && $ruser->{'perms'} eq 'r') { push(@roreps, $r->{'rep'}); } } local %defs; &read_file("$module_config_directory/defaults.$dom->{'id'}", \%defs); if (!$suser && !@rwreps) { # Use default repositories @rwreps = split(/\s+/, $defs{'reps'}); } @rwreps = sort { $a cmp $b } @rwreps; @roreps = sort { $a cmp $b } @roreps; @reps = sort { $a->{'rep'} cmp $b->{'rep'} } @reps; local @inputs = ( $input_name."_rwreps_opts", $input_name."_rwreps_vals", $input_name."_rwreps_add", $input_name."_rwreps_remove", $input_name."_roreps_opts", $input_name."_roreps_vals", $input_name."_roreps_add", $input_name."_roreps_remove", ); local $hasuser = $suser || $new && $defs{'svn'}; local $dis = $hasuser ? 0 : 1; if (&get_webmin_version() < 1.501) { # Only Webmin 1.501 and later support disabling multi-select properly $dis = 0; @inputs = ( ); } local $jsenable = &js_disable_inputs([ ], \@inputs, "onClick"); local $jsdisable = &js_disable_inputs(\@inputs, [ ], "onClick"); return &ui_table_row(&hlink($text{'mail_svn'}, "svn"), &ui_radio($input_name, $hasuser ? 1 : 0, [ [ 1, $text{'yes'}, $jsenable ], [ 0, $text{'no'}, $jsdisable ] ])). &ui_table_row(&hlink($text{'mail_reps'}, "reps"), &ui_multi_select( $input_name."_rwreps", [ map { [ $_, $_ ] } @rwreps ], [ map { [ $_->{'rep'}, $_->{'rep'} ] } @reps ], 3, 0, $hasuser ? 0 : 1, $text{'mail_repsopts'}, $text{'mail_repsin'})). &ui_table_row(&hlink($text{'mail_roreps'}, "roreps"), &ui_multi_select( $input_name."_roreps", [ map { [ $_, $_ ] } @roreps ], [ map { [ $_->{'rep'}, $_->{'rep'} ] } @reps ], 3, 0, $dis, $text{'mail_repsopts'}, $text{'mail_repsin'})); } # mailbox_validate(&user, &olduser, &in, new, &domain) # Validates inputs generated by mailbox_inputs, and returns either undef on # success or an error message sub mailbox_validate { local ($user, $olduser, $in, $new, $dom) = @_; return undef if (!$dom || !$dom->{$module_name}); if ($in->{$input_name}) { local @users = &list_users($dom); local $un = &virtual_server::remove_userdom($user->{'user'}, $dom); local $oun = &virtual_server::remove_userdom($olduser->{'user'}, $dom); local ($suser) = grep { $_->{'user'} eq $oun } @users; # Make sure SVN user doesn't clash if ($new || $user->{'user'} ne $olduser->{'user'}) { local ($clash) = grep { $_->{'user'} eq $un } @users; return &text('mail_clash', $un) if ($clash); } # Make sure a password is given if needed if (!defined($user->{'plainpass'}) && !$user->{'pass_digest'} && !$suser && $user->{'user'} ne $dom->{'user'} && $config{'auth'} eq 'Digest') { return $text{'mail_pass'}; } # Make sure rw and ro repos don't clash local @rwreps = split(/\r?\n/, $in->{$input_name."_rwreps"}); local @roreps = split(/\r?\n/, $in->{$input_name."_roreps"}); foreach my $r (@rwreps) { &indexof($r, @roreps) < 0 || return &text('mail_repoclash', $r); } } return undef; } # mailbox_save(&user, &olduser, &in, new, &domain) # Updates the user based on inputs generated by mailbox_inputs sub mailbox_save { local ($user, $olduser, $in, $new, $dom) = @_; return undef if (!$dom || !$dom->{$module_name}); &foreign_require("htaccess-htpasswd", "htaccess-lib.pl"); local @users = &list_users($dom); local $suser; local $un = &virtual_server::remove_userdom($user->{'user'}, $dom); local $oun = &virtual_server::remove_userdom($olduser->{'user'}, $dom); local $rv; &lock_file(&passwd_file($dom)); &lock_file(&conf_file($dom)); if (!$new) { ($suser) = grep { $_->{'user'} eq $oun } @users; } if ($in->{$input_name} && !$suser) { # Add the user local $newuser = { 'user' => $un, 'enabled' => 1 }; &set_user_password($newuser, $user, $dom); &virtual_server::write_as_domain_user($dom, sub { &htaccess_htpasswd::create_user( $newuser, &passwd_file($dom)) }); &virtual_server::set_permissions_as_domain_user( $dom, 0755, &passwd_file($dom)); $rv = 1; } elsif (!$in->{$input_name} && $suser) { # Delete the user &virtual_server::write_as_domain_user($dom, sub { &htaccess_htpasswd::delete_user($suser) }); $rv = 0; } elsif ($in->{$input_name} && $suser) { # Update the user $suser->{'user'} = $un; if ($user->{'passmode'} == 3) { if ($config{'auth'} eq 'Digest') { $suser->{'pass'} = $user->{'pass_digest'} || &htaccess_htpasswd::digest_password( $un, $dom->{'dom'}, $user->{'plainpass'}); } else { $suser->{'pass'} = $user->{'pass_crypt'} || $user->{'pass'}; } } &virtual_server::write_as_domain_user($dom, sub { &htaccess_htpasswd::modify_user($suser) }); $rv = 1; } &unlock_file(&passwd_file($dom)); &unlock_file(&conf_file($dom)); # Update list of repositories user has access to local %canrwreps = map { $_, 1 } split(/\r?\n/, $in->{$input_name."_rwreps"}); local %canroreps = map { $_, 1 } split(/\r?\n/, $in->{$input_name."_roreps"}); if (!$in->{$input_name}) { %canrwreps = ( ); %canroreps = ( ); } foreach my $r (&list_reps($dom)) { local @rusers = &list_rep_users($dom, $r->{'rep'}); local ($ruser) = grep { $_->{'user'} eq $oun } @rusers; @rusers = grep { $_ ne $ruser } @rusers; if ($canrwreps{$r->{'rep'}}) { push(@rusers, { 'user' => $un, 'perms' => 'rw' }); } elsif ($canroreps{$r->{'rep'}}) { push(@rusers, { 'user' => $un, 'perms' => 'r' }); } if ($ruser || $canrwreps{$r->{'rep'}} || $canroreps{$r->{'rep'}}) { # Only save if user was there before or is now &save_rep_users($dom, $r, \@rusers); } } return $rv; } # mailbox_modify(&user, &old, &domain) sub mailbox_modify { local ($user, $olduser, $dom) = @_; return undef if (!$dom || !$dom->{$module_name}); &foreign_require("htaccess-htpasswd", "htaccess-lib.pl"); local @users = &list_users($dom); local $un = &virtual_server::remove_userdom($user->{'user'}, $dom); local $oun = &virtual_server::remove_userdom($olduser->{'user'}, $dom); local ($suser) = grep { $_->{'user'} eq $oun } @users; return undef if (!$suser); &lock_file(&passwd_file($dom)); &lock_file(&conf_file($dom)); if ($un ne $oun && $suser) { # User was re-named $suser->{'user'} = $un; &htaccess_htpasswd::modify_user($suser); foreach my $r (&list_reps($dom)) { local @rusers = &list_rep_users($dom, $r->{'rep'}); local ($ruser) = grep { $_->{'user'} eq $oun } @rusers; if ($ruser) { $ruser->{'user'} = $un; &save_rep_users($dom, $r, \@rusers); } } } if ($user->{'passmode'} == 3) { # Password was changed if ($config{'auth'} eq 'Digest') { $suser->{'pass'} = $user->{'pass_digest'} || &htaccess_htpasswd::digest_password( $un, $dom->{'dom'}, $user->{'plainpass'}); } else { $suser->{'pass'} = $user->{'pass_crypt'} || &htaccess_htpasswd::encrypt_password( $user->{'plainpass'}); } &virtual_server::write_as_domain_user($dom, sub { &htaccess_htpasswd::modify_user($suser) }); } &unlock_file(&passwd_file($dom)); &unlock_file(&conf_file($dom)); } # mailbox_delete(&user, &domain) # Removes any extra features for this user sub mailbox_delete { local ($user, $dom) = @_; return undef if (!$dom || !$dom->{$module_name}); &foreign_require("htaccess-htpasswd", "htaccess-lib.pl"); &lock_file(&passwd_file($dom)); &lock_file(&conf_file($dom)); local @users = &list_users($dom); local $un = &virtual_server::remove_userdom($user->{'user'}, $dom); local ($suser) = grep { $_->{'user'} eq $un } @users; if ($suser) { &virtual_server::write_as_domain_user($dom, sub { &htaccess_htpasswd::delete_user($suser) }); } # Remove from all repositories foreach $r (&list_reps($dom)) { local @rusers = &list_rep_users($dom, $r->{'rep'}); local ($ruser) = grep { $_->{'user'} eq $un } @rusers; local @newrusers = grep { $_ ne $ruser } @rusers; if (@newrusers != @rusers) { &save_rep_users($dom, $r, \@newrusers); } } &unlock_file(&passwd_file($dom)); &unlock_file(&conf_file($dom)); } # mailbox_header(&domain) # Returns a column header for the user display, or undef for none sub mailbox_header { if ($_[0]->{$module_name}) { @column_users = &list_users($_[0]); return $text{'mail_header'}; } else { return undef; } } # mailbox_column(&user, &domain) # Returns the text to display in the column for some user sub mailbox_column { local ($user, $dom) = @_; local $un = &virtual_server::remove_userdom($user->{'user'}, $dom); local ($duser) = grep { $_->{'user'} eq $un } @column_users; return $duser ? $text{'yes'} : $text{'no'}; } # mailbox_defaults_inputs(&defs, &domain) # Returns HTML for editing defaults for plugin-related settings for new # users in this virtual server sub mailbox_defaults_inputs { local ($defs, $dom) = @_; if ($dom->{$module_name}) { local %defs; &read_file("$module_config_directory/defaults.$dom->{'id'}", \%defs); local @reps = &list_reps($dom); return &ui_table_row($text{'mail_svn'}, &ui_yesno_radio($input_name, int($defs{'svn'})))."\n". &ui_table_row($text{'mail_reps'}, &ui_select($input_name."_reps", [ split(/\s+/, $defs{'reps'}) ], [ map { [ $_->{'rep'}, $_->{'rep'} ] } @reps ], 3, 1)); } } # mailbox_defaults_parse(&defs, &domain, &in) # Parses the inputs created by mailbox_defaults_inputs, and updates a config # file internal to this module to store them sub mailbox_defaults_parse { local ($defs, $dom, $in) = @_; if ($dom->{$module_name}) { local %defs; &read_file("$module_config_directory/defaults.$dom->{'id'}", \%defs); $defs{'svn'} = $in->{$input_name}; $defs{'reps'} = join(" ", split(/\0/, $in->{$input_name."_reps"})); &write_file("$module_config_directory/defaults.$dom->{'id'}", \%defs); } } # template_input(&template) # Returns HTML for editing per-template options for this plugin sub template_input { local ($tmpl) = @_; local $v = $tmpl->{$module_name."limit"}; $v = "none" if (!defined($v) && $tmpl->{'default'}); return &ui_table_row($text{'tmpl_limit'}, &ui_radio($input_name."_mode", $v eq "" ? 0 : $v eq "none" ? 1 : 2, [ $tmpl->{'default'} ? ( ) : ( [ 0, $text{'default'} ] ), [ 1, $text{'tmpl_unlimit'} ], [ 2, $text{'tmpl_atmost'} ] ])."\n". &ui_textbox($input_name, $v eq "none" ? undef : $v, 10)); } # template_parse(&template, &in) # Updates the given template object by parsing the inputs generated by # template_input. All template fields must start with the module name. sub template_parse { local ($tmpl, $in) = @_; if ($in->{$input_name.'_mode'} == 0) { $tmpl->{$module_name."limit"} = ""; } elsif ($in->{$input_name.'_mode'} == 1) { $tmpl->{$module_name."limit"} = "none"; } else { $in->{$input_name} =~ /^\d+$/ || &error($text{'tmpl_elimit'}); $tmpl->{$module_name."limit"} = $in->{$input_name}; } } 1;y~or5J={Eeu磝Qk ᯘG{?+]ן?wM3X^歌>{7پK>on\jy Rg/=fOroNVv~Y+ NGuÝHWyw[eQʨSb> >}Gmx[o[<{Ϯ_qFvM IENDB`