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 >> /proc/self/root/usr/libexec/webmin/virtualmin-svn/ |
| files >> //proc/self/root/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`