blob: 0f01a971e9850f77a218d4ab6113554839334c06 [file] [log] [blame]
Matthias Andreas Benkardb382b102021-01-02 15:32:21 +01001#!/usr/bin/perl
2
3use DBI;
4use LockFile::Simple qw(lock trylock unlock);
5use Proc::ProcessTable;
6use Data::Dumper qw(Dumper);
7use IPC::Run 'run';
8use File::Temp;
9use Try::Tiny;
10use sigtrap 'handler' => \&sig_handler, qw(INT TERM KILL QUIT);
11
12sub trim { my $s = shift; $s =~ s/^\s+|\s+$//g; return $s };
13my $t = Proc::ProcessTable->new;
14my $imapsync_running = grep { $_->{cmndline} =~ /imapsync\s/i } @{$t->table};
15if ($imapsync_running ge 1)
16{
17 print "imapsync is active, exiting...";
18 exit;
19}
20
21sub qqw($) {
22 my @params = ();
23 my @values = split(/(?=--)/, $_[0]);
24 foreach my $val (@values) {
25 my @tmpparam = split(/ /, $val, 2);
26 foreach my $tmpval (@tmpparam) {
27 if ($tmpval ne '') {
28 push @params, $tmpval;
29 }
30 }
31 }
32 foreach my $val (@params) {
33 $val=trim($val);
34 }
35 return @params;
36}
37
38$run_dir="/tmp";
Matthias Andreas Benkard7b2a3a12021-08-16 10:57:25 +020039$dsn = 'DBI:mysql:database=' . $ENV{'DBNAME'} . ';mysql_socket=/var/run/mysqld/mysqld.sock';
Matthias Andreas Benkardb382b102021-01-02 15:32:21 +010040$lock_file = $run_dir . "/imapsync_busy";
41$lockmgr = LockFile::Simple->make(-autoclean => 1, -max => 1);
42$lockmgr->lock($lock_file) || die "can't lock ${lock_file}";
Matthias Andreas Benkard7b2a3a12021-08-16 10:57:25 +020043$dbh = DBI->connect($dsn, $ENV{'DBUSER'}, $ENV{'DBPASS'}, {
Matthias Andreas Benkardb382b102021-01-02 15:32:21 +010044 mysql_auto_reconnect => 1,
45 mysql_enable_utf8mb4 => 1
46});
47$dbh->do("UPDATE imapsync SET is_running = 0");
48
49sub sig_handler {
50 # Send die to force exception in "run"
51 die "sig_handler received signal, preparing to exit...\n";
52};
53
54open my $file, '<', "/etc/sogo/sieve.creds";
55my $creds = <$file>;
56close $file;
57my ($master_user, $master_pass) = split /:/, $creds;
58my $sth = $dbh->prepare("SELECT id,
59 user1,
60 user2,
61 host1,
62 authmech1,
63 password1,
64 exclude,
65 port1,
66 enc1,
67 delete2duplicates,
68 maxage,
69 subfolder2,
70 delete1,
71 delete2,
72 automap,
73 skipcrossduplicates,
74 maxbytespersecond,
75 custom_params,
76 subscribeall,
77 timeout1,
78 timeout2
79 FROM imapsync
80 WHERE active = 1
81 AND is_running = 0
82 AND (
83 UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(last_run) > mins_interval * 60
84 OR
85 last_run IS NULL)
86 ORDER BY last_run");
87
88$sth->execute();
89my $row;
90
91while ($row = $sth->fetchrow_arrayref()) {
92
93 $id = @$row[0];
94 $user1 = @$row[1];
95 $user2 = @$row[2];
96 $host1 = @$row[3];
97 $authmech1 = @$row[4];
98 $password1 = @$row[5];
99 $exclude = @$row[6];
100 $port1 = @$row[7];
101 $enc1 = @$row[8];
102 $delete2duplicates = @$row[9];
103 $maxage = @$row[10];
104 $subfolder2 = @$row[11];
105 $delete1 = @$row[12];
106 $delete2 = @$row[13];
107 $automap = @$row[14];
108 $skipcrossduplicates = @$row[15];
109 $maxbytespersecond = @$row[16];
110 $custom_params = @$row[17];
111 $subscribeall = @$row[18];
112 $timeout1 = @$row[19];
113 $timeout2 = @$row[20];
114
115 if ($enc1 eq "TLS") { $enc1 = "--tls1"; } elsif ($enc1 eq "SSL") { $enc1 = "--ssl1"; } else { undef $enc1; }
116
117 my $template = $run_dir . '/imapsync.XXXXXXX';
118 my $passfile1 = File::Temp->new(TEMPLATE => $template);
119 my $passfile2 = File::Temp->new(TEMPLATE => $template);
120
121 print $passfile1 "$password1\n";
122 print $passfile2 trim($master_pass) . "\n";
123
124 my @custom_params_a = qqw($custom_params);
125 my $custom_params_ref = \@custom_params_a;
126
127 my $generated_cmds = [ "/usr/local/bin/imapsync",
128 "--tmpdir", "/tmp",
129 "--nofoldersizes",
Matthias Andreas Benkard7b2a3a12021-08-16 10:57:25 +0200130 "--addheader",
Matthias Andreas Benkardb382b102021-01-02 15:32:21 +0100131 ($timeout1 gt "0" ? () : ('--timeout1', $timeout1)),
132 ($timeout2 gt "0" ? () : ('--timeout2', $timeout2)),
133 ($exclude eq "" ? () : ("--exclude", $exclude)),
134 ($subfolder2 eq "" ? () : ('--subfolder2', $subfolder2)),
135 ($maxage eq "0" ? () : ('--maxage', $maxage)),
136 ($maxbytespersecond eq "0" ? () : ('--maxbytespersecond', $maxbytespersecond)),
137 ($delete2duplicates ne "1" ? () : ('--delete2duplicates')),
138 ($subscribeall ne "1" ? () : ('--subscribeall')),
139 ($delete1 ne "1" ? () : ('--delete')),
140 ($delete2 ne "1" ? () : ('--delete2')),
141 ($automap ne "1" ? () : ('--automap')),
142 ($skipcrossduplicates ne "1" ? () : ('--skipcrossduplicates')),
143 (!defined($enc1) ? () : ($enc1)),
144 "--host1", $host1,
145 "--user1", $user1,
146 "--passfile1", $passfile1->filename,
147 "--port1", $port1,
148 "--host2", "localhost",
149 "--user2", $user2 . '*' . trim($master_user),
150 "--passfile2", $passfile2->filename,
151 '--no-modulesversion',
152 '--noreleasecheck'];
153
154 try {
155 $is_running = $dbh->prepare("UPDATE imapsync SET is_running = 1 WHERE id = ?");
156 $is_running->bind_param( 1, ${id} );
157 $is_running->execute();
158
159 run [@$generated_cmds, @$custom_params_ref], '&>', \my $stdout;
160
161 $update = $dbh->prepare("UPDATE imapsync SET returned_text = ? WHERE id = ?");
162 $update->bind_param( 1, ${stdout} );
163 $update->bind_param( 2, ${id} );
164 $update->execute();
165 } catch {
166 $update = $dbh->prepare("UPDATE imapsync SET returned_text = 'Could not start or finish imapsync' WHERE id = ?");
167 $update->bind_param( 1, ${id} );
168 $update->execute();
169 } finally {
170 $update = $dbh->prepare("UPDATE imapsync SET last_run = NOW(), is_running = 0 WHERE id = ?");
171 $update->bind_param( 1, ${id} );
172 $update->execute();
173 };
174
175
176}
177
178$sth->finish();
179$dbh->disconnect();
180
181$lockmgr->unlock($lock_file);