our $usage2 = <<'END';
actions
create [REDIRECT] [#COMMENT] (default for REDIRECT is your username)
- update LOCAL-PART [REDIRECT] [#COMMENT]
- show LOCAL-PART
+ update ADDR [REDIRECT] [#COMMENT]
+ show ADDR
list
list-actions
empty string for REDIRECT means reject
our $usage3 = <<'END';
privileged actions
list-user USER
- insert-exact LOCAL-PART USER REDIRECT COMMENT
- donate LOCAL-PART USER
+ insert-exact ADDR USER REDIRECT COMMENT
+ donate ADDR USER
enable-user|disable-user USER
END
+#/
use strict;
return $v;
}
+sub addr2localpart ($) {
+ my ($addr) = @_;
+ return $addr if $addr !~ m/\@/;
+ die "address not in correct domain (\@$dom)\n" unless $' eq $dom; #';
+ return $`; #`;
+}
+
+sub nextarg_addr () {
+ return addr2localpart nextarg;
+}
+
sub nomoreargs () {
die "too many arguments\n" if @ARGV;
}
return $row;
}
-sub action_create {
- my $newrow = rhsargs({'redirect'=>$user, 'comment'=>''});
- open R, "/dev/urandom" or die $!;
- binmode R;
- my $countq = $dbh->prepare("SELECT count(*) FROM addrs WHERE user=?");
- $countq->execute($user);
- my ($count) = $countq->fetchrow_array();
- die unless defined $count;
- die "too many aliases for this user\n" if $count >= $maxperuser;
- my $q = $dbh->prepare("SELECT localpart FROM addrs WHERE localpart=?");
+sub local_part_inuse ($) {
+ my ($s) = @_;
+ our $checkexist_q ||=
+ $dbh->prepare("SELECT localpart FROM addrs WHERE localpart=?");
+ $checkexist_q->execute($s);
+ my $row = $checkexist_q->fetchrow_arrayref();
+ return !!$row;
+}
+
+sub generate_local_part () {
my $s;
for (;;) {
$s = chr(ord('a')+goodrand(26));
: ord('0')+($v-26));
}
# print STDERR "$s\n";
- $q->execute($s);
- my $row = $q->fetchrow_arrayref();
- last if !$row;
- $dbh->abort();
+ last if !local_part_inuse($s);
}
+ return $s;
+}
+
+sub prepare_create () {
+ my $countq = $dbh->prepare("SELECT count(*) FROM addrs WHERE user=?");
+ $countq->execute($user);
+ my ($count) = $countq->fetchrow_array();
+ die unless defined $count;
+ die "too many aliases for this user\n" if $count >= $maxperuser;
+ open R, "/dev/urandom" or die $!;
+ binmode R;
+}
+
+sub action_create {
+ my $newrow = rhsargs({'redirect'=>$user, 'comment'=>''});
+ prepare_create();
$newrow->{'user'} = $user;
- $newrow->{'localpart'} = $s;
+ $newrow->{'localpart'} = generate_local_part();
insertrow($newrow);
$dbh->commit();
prow($newrow);
}
sub action_update {
- my $localpart = nextarg;
+ my $localpart = nextarg_addr;
my $updrow = rhsargs({});
nomoreargs;
begin_row($localpart);
}
sub action_show {
- my $localpart = nextarg;
+ my $localpart = nextarg_addr;
nomoreargs;
my $row = begin_row($localpart);
prow($row);
sub action_insert_exact {
die unless $priv;
my $row = { };
- $row->{'localpart'} = nextarg;
+ $row->{'localpart'} = nextarg_addr;
$row->{'user'} = $user = nextarg;
$row->{'redirect'} = nextarg;
$row->{'comment'} = nextarg;
sub action_donate {
die unless $priv;
- my $localpart = nextarg;
+ my $localpart = nextarg_addr;
my $newuser = nextarg;
nomoreargs;
begin_row($localpart);
$user = ((getpwuid $<)[0]) or die;
}
-$usage2 .= "LOCAL-PART is implicitly qualified with \@$dom\n"
- if defined $qualdom;
+$usage2 .= defined $dom
+ ? "ADDR may be a local part, implicitly qualified with \@$dom\n"
+ : "ADDR must be a local part (only)\n";
$usage2 .= "REDIRECT is implicitly qualified with \@$qualdom if it has no \@\n"
if defined $qualdom;