]> git.g-eek.se Git - interimap.git/commitdiff
Allow custom database path.
authorGuilhem Moulin <guilhem@fripost.org>
Thu, 23 Jul 2015 19:15:01 +0000 (21:15 +0200)
committerGuilhem Moulin <guilhem@fripost.org>
Thu, 23 Jul 2015 19:15:01 +0000 (21:15 +0200)
imapsync
lib/Net/IMAP/Sync.pm

index a18e4cdef5f4b63db976d16b9947198208319c01..4ad95f3f6306318cf765cabb11f8876f7593b444 100755 (executable)
--- a/imapsync
+++ b/imapsync
@@ -47,10 +47,29 @@ usage(1) unless GetOptions(\%CONFIG, qw/debug help|h config=s quiet|q oneshot|1/
 usage(0) if $CONFIG{help};
 
 
-my $CONFFILE = delete $CONFIG{config} // 'imapsync';
-my $CACHEDIR = './imapsync.cache'; # XXX use a config option
-my $DBFILE = "$CACHEDIR/imap.guilhem.org.db";
-my $LOCKFILE = "$CACHEDIR/.imap.guilhem.org.lck";
+my $CONF = read_config( delete $CONFIG{config} // $NAME
+                      , [qw/_ local remote/]
+                      , database => qr/\A(\P{Control}+)\z/ );
+my ($DBFILE, $LOCKFILE);
+
+{
+    $DBFILE = $CONF->{_}->{database} if defined $CONF->{_};
+    $DBFILE //= $CONF->{remote}->{host}.'.db' if defined $CONF->{remote};
+    $DBFILE //= $CONF->{local}->{host}. '.db' if defined $CONF->{local};
+    die "Missing option database" unless defined $DBFILE;
+
+    unless ($DBFILE =~ /\A\//) {
+        my $dir = ($ENV{XDG_DATA_HOME} // "$ENV{HOME}/.local/share") .'/'. $NAME;
+        $dir =~ /\A(\/\p{Print}+)\z/ or die "Insecure $dir";
+        $dir = $1;
+        $DBFILE = $dir .'/'. $DBFILE;
+        unless (-d $dir) {
+            mkdir $dir, 0700 or die "Cannot mkdir $dir: $!\n";
+        }
+    }
+
+    $LOCKFILE = $DBFILE =~ s/([^\/]+)\z/.$1.lck/r;
+}
 my ($DBH, $IMAP);
 
 
@@ -67,10 +86,7 @@ $SIG{$_} = sub { clean(); die "$!\n"; } foreach qw/INT TERM/;
 #############################################################################
 # Lock the database
 {
-    if (!-d $CACHEDIR) {
-        mkdir $CACHEDIR, 0700 or die "Cannot mkdir $CACHEDIR: $!\n";
-    }
-    elsif (-f $LOCKFILE) {
+    if (-f $LOCKFILE) {
         open my $lock, '<', $LOCKFILE or die "Cannot open $LOCKFILE: $!\n";
         my $pid = <$lock>;
         close $lock;
@@ -164,7 +180,7 @@ sub msg($@) {
 # Connect to the local and remote IMAP servers
 
 foreach my $name (qw/local remote/) {
-    my %config = Net::IMAP::Sync::read_config($CONFFILE, $name);
+    my %config = %{$CONF->{$name}};
     $config{$_} = $CONFIG{$_} foreach keys %CONFIG;
     $config{enable} = 'QRESYNC';
     $config{name} = $name;
index 2c2a4348028a783a234e55d03e939bb947b50556..2aff76cd7b57420d8c196db1e7dbc1309ef21f96 100644 (file)
@@ -57,13 +57,13 @@ my %OPTIONS = (
 #############################################################################
 # Utilities
 
-# read_config($conffile, $section, %opts)
-#   Read $conffile's default section, then $section (which takes
-#   precedence).  %opts extends %OPTIONS and maps each option to a
-#   regexp validating its values.
+# read_config($conffile, $sections, %opts)
+#   Read $conffile's default section, then each section in the array
+#   reference $section (which takes precedence).  %opts extends %OPTIONS
+#   and maps each option to a regexp validating its values.
 sub read_config($$%) {
     my $conffile = shift;
-    my $section = shift;
+    my $sections = shift;
     my %opts = (%OPTIONS, @_);
 
     $conffile = ($ENV{XDG_CONFIG_HOME} // "$ENV{HOME}/.config") .'/'. $conffile
@@ -73,26 +73,32 @@ sub read_config($$%) {
         unless defined $conffile and -f $conffile and -r $conffile;
 
     my $h = Config::Tiny::->read($conffile);
-    die "No such section $section\n" unless defined $h->{$section};
-
-    my $conf = $h->{_}; # default section
-    $conf->{$_} = $h->{$section}->{$_} foreach keys %{$h->{$section}};
-
-    # default values
-    $conf->{type} //= 'imaps';
-    $conf->{host} //= 'localhost';
-    $conf->{port} //= $conf->{type} eq 'imaps' ? 993 : $conf->{type} eq 'imap' ? 143 : undef;
-    $conf->{auth} //= 'PLAIN LOGIN';
-    $conf->{STARTTLS} //= 'TRUE';
-
-    # untaint and validate the config
-    foreach my $k (keys %$conf) {
-        die "Invalid option $k\n" unless defined $opts{$k};
-        next unless defined $conf->{$k};
-        die "Invalid option $k = $conf->{$k}\n" unless $conf->{$k} =~ $opts{$k};
-        $conf->{$k} = $1;
+
+    my %configs;
+    foreach my $section (@$sections) {
+        my $conf = { %{$h->{_}} }; # default section
+        $configs{$section} = $conf;
+        next unless defined $section and $section ne '_';
+
+        die "No such section $section\n" unless defined $h->{$section};
+        $conf->{$_} = $h->{$section}->{$_} foreach keys %{$h->{$section}};
+
+        # default values
+        $conf->{type} //= 'imaps';
+        $conf->{host} //= 'localhost';
+        $conf->{port} //= $conf->{type} eq 'imaps' ? 993 : $conf->{type} eq 'imap' ? 143 : undef;
+        $conf->{auth} //= 'PLAIN LOGIN';
+        $conf->{STARTTLS} //= 'TRUE';
+
+        # untaint and validate the config
+        foreach my $k (keys %$conf) {
+            die "Invalid option $k\n" unless defined $opts{$k};
+            next unless defined $conf->{$k};
+            die "Invalid option $k = $conf->{$k}\n" unless $conf->{$k} =~ $opts{$k};
+            $conf->{$k} = $1;
+        }
     }
-    return %$conf;
+    return \%configs;
 }