You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
180 lines
6.0 KiB
180 lines
6.0 KiB
#!@l_prefix@/bin/perl |
|
## |
|
## dbmail-folders -- DBMail Folders Creation Utility |
|
## Copyright (c) 2007-2008 Ralf S. Engelschall <rse@engelschall.com> |
|
## |
|
## See also: |
|
## http://www.dbmail.org/dokuwiki/doku.php?id=shared-mbox |
|
## http://library.mobrien.com/dbmailadministrator/DBMA_ACLs.htm |
|
## |
|
|
|
# language requirements |
|
require 5.008; |
|
use strict; |
|
use warnings; |
|
|
|
# load extensions |
|
use Getopt::Long; |
|
use DBI; |
|
use DBD::Pg; |
|
use DBIx::Simple; |
|
|
|
# command line argument parsing |
|
my $opt = { |
|
-help => 0, |
|
-hostname => ($ENV{"PGHOST"} || "localhost"), |
|
-database => ($ENV{"PGDATABASE"} || "dbmail" ), |
|
-username => ($ENV{"PGUSER"} || "dbmail" ), |
|
-password => ($ENV{"PGPASSWORD"} || "dbmail" ), |
|
}; |
|
my $p = new Getopt::Long::Parser; |
|
$p->configure("bundling"); |
|
$p->getoptions( |
|
'h|help' => \$opt->{-help}, |
|
'H|hostname=s' => \$opt->{-hostname}, |
|
'D|database=s' => \$opt->{-database}, |
|
'U|username=s' => \$opt->{-username}, |
|
'P|password=s' => \$opt->{-password}, |
|
) || die "option parsing failed"; |
|
undef $p; |
|
if ($opt->{-help} or @ARGV < 2) { |
|
printf(STDERR "USAGE: dbmail-folders [-h|--help]\n"); |
|
printf(STDERR " [-H|--hostname <db-hostname>] [-D|--database <db-name>]\n"); |
|
printf(STDERR " [-U|--username <db-username>] [-P|--password <db-password>]\n"); |
|
printf(STDERR " <owner> <folder> [[{ro,rw}:]<user> ...]\n"); |
|
printf(STDERR "EXAMPLES:\n"); |
|
printf(STDERR "1. # create public folder #Public/<folder> (fully shared)\n"); |
|
printf(STDERR " \$ dbmail-folders __public__ <folder> anyone\n"); |
|
printf(STDERR "2. # create personal shared folder #Users/<owner>/<folder> (fully shared)\n"); |
|
printf(STDERR " \$ dbmail-folders <owner> <folder> anyone\n"); |
|
printf(STDERR "3. # create personal shared folder #Users/<owner>/<folder> (fully shared, different access)\n"); |
|
printf(STDERR " \$ dbmail-folders <owner> <folder> ro:anyone rw:<proxy>\n"); |
|
printf(STDERR "4. # create personal shared folder #Users/<owner>/<folder> (partly shared)\n"); |
|
printf(STDERR " \$ dbmail-folders <owner> <folder> <user1> <user2> ...\n"); |
|
printf(STDERR "5. # create personal private folder #Users/<owner>/<folder> (not shared)\n"); |
|
printf(STDERR " \$ dbmail-folders <owner> <folder>\n"); |
|
exit($opt->{-help} ? 0 : 1); |
|
} |
|
my $owner = shift(@ARGV); |
|
my $folder = shift(@ARGV); |
|
my @users = @ARGV; |
|
|
|
# connect to DBMail's PostgreSQL-based backend RDBMS |
|
my $db = DBIx::Simple->connect( |
|
sprintf("dbi:Pg:host=%s;dbname=%s", $opt->{-hostname}, $opt->{-database}), |
|
$opt->{-username}, $opt->{-password}, |
|
{ RaiseError => 1, AutoCommit => 1 } |
|
); |
|
die "failed to connect to database" |
|
if (not defined($db)); |
|
|
|
# ensure that the folder owner exists |
|
my ($owner_id) = $db->query(q{ |
|
SELECT user_idnr |
|
FROM dbmail_users |
|
WHERE userid = ?; |
|
}, $owner)->flat(); |
|
if (not defined $owner_id) { |
|
printf(STDERR "dbmail-folders:ERROR: folder owner \"%s\" not existing\n", $owner); |
|
exit(1); |
|
} |
|
|
|
# check whether folder already exists |
|
my ($mailbox_id) = $db->query(q{ |
|
SELECT mailbox_idnr |
|
FROM dbmail_mailboxes |
|
WHERE owner_idnr = ? AND name = ?; |
|
}, $owner_id, $folder)->flat(); |
|
if (not defined $mailbox_id) { |
|
# create it if still not existing |
|
$db->query(q{ |
|
INSERT |
|
INTO dbmail_mailboxes |
|
( owner_idnr, name, |
|
seen_flag, answered_flag, deleted_flag, flagged_flag, recent_flag, draft_flag, |
|
no_inferiors, no_select, permission ) |
|
VALUES ( ?, ?, |
|
1, 1, 1, 1, 1, 1, |
|
0, 0, 2 ); |
|
}, $owner_id, $folder) |
|
or printf(STDERR "dbmail-folders:ERROR: unable to create folder \"%s/%s\": %s\n", $owner, $folder, $db->error()), exit(1); |
|
($mailbox_id) = $db->query(q{ |
|
SELECT mailbox_idnr |
|
FROM dbmail_mailboxes |
|
WHERE owner_idnr = ? AND name = ?; |
|
}, $owner_id, $folder)->flat(); |
|
if (not defined $mailbox_id) { |
|
printf(STDERR "dbmail-folders:ERROR: unable to determine id of newly created folder\n"); |
|
exit(1); |
|
} |
|
} |
|
|
|
# optionally grant access to folder for additional users (beside folder owner) |
|
$db->query(q{ |
|
DELETE |
|
FROM dbmail_acl |
|
WHERE mailbox_id = ?; |
|
}, $mailbox_id); |
|
foreach my $user (@ARGV) { |
|
my $mode = "rw"; |
|
if ($user =~ m/^(r[ow]):(.+)$/) { |
|
$mode = $1; |
|
$user = $2; |
|
} |
|
my ($user_id) = $db->query(q{ |
|
SELECT user_idnr |
|
FROM dbmail_users |
|
WHERE userid = ?; |
|
}, $user)->flat(); |
|
if (not defined $user_id) { |
|
printf(STDERR "dbmail-folders:WARNING: user \"%s\" not existing\n", $user); |
|
next; |
|
} |
|
if ($mode eq "rw") { |
|
$db->query(q{ |
|
INSERT |
|
INTO dbmail_acl |
|
( user_id, mailbox_id, |
|
lookup_flag, read_flag, seen_flag, write_flag, insert_flag, |
|
post_flag, create_flag, delete_flag, administer_flag ) |
|
VALUES ( ?, ?, |
|
1, 1, 1, 1, 1, |
|
1, 1, 1, 1 ); |
|
}, $user_id, $mailbox_id); |
|
} |
|
else { |
|
$db->query(q{ |
|
INSERT |
|
INTO dbmail_acl |
|
( user_id, mailbox_id, |
|
lookup_flag, read_flag, seen_flag, write_flag, insert_flag, |
|
post_flag, create_flag, delete_flag, administer_flag ) |
|
VALUES ( ?, ?, |
|
1, 1, 0, 0, 0, |
|
0, 0, 0, 0 ); |
|
}, $user_id, $mailbox_id); |
|
} |
|
} |
|
|
|
# make sure at least owner is subscribed to folder |
|
my ($exists) = $db->query(q{ |
|
SELECT 1 |
|
FROM dbmail_subscription |
|
WHERE user_id = ? AND mailbox_id = ?; |
|
}, $owner_id, $mailbox_id)->flat(); |
|
if (not (defined $exists and $exists)) { |
|
$db->query(q{ |
|
INSERT |
|
INTO dbmail_subscription |
|
( user_id, mailbox_id ) |
|
VALUES ( ?, ? ); |
|
}, $owner_id, $mailbox_id); |
|
} |
|
|
|
# disconnect from DBMail's PostgreSQL-based backend RDBMS |
|
$db->disconnect(); |
|
undef $db; |
|
|
|
# die gracefully |
|
exit(0); |
|
|
|
|