blob: 5b297abd9c4997b0400e82d5ca15d3966eaf9e1f [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 {
Matthias Andreas Benkard12a57352021-12-28 18:02:04 +0100155 $is_running = $dbh->prepare("UPDATE imapsync SET is_running = 1, success = NULL, exit_status = NULL WHERE id = ?");
Matthias Andreas Benkardb382b102021-01-02 15:32:21 +0100156 $is_running->bind_param( 1, ${id} );
157 $is_running->execute();
Matthias Andreas Benkard12a57352021-12-28 18:02:04 +0100158
Matthias Andreas Benkardb382b102021-01-02 15:32:21 +0100159 run [@$generated_cmds, @$custom_params_ref], '&>', \my $stdout;
Matthias Andreas Benkard12a57352021-12-28 18:02:04 +0100160
161 # check exit code and status
162 ($exit_code, $exit_status) = ($stdout =~ m/Exiting\swith\sreturn\svalue\s(\d+)\s\(([^:)]+)/);
163
164 $success = 0;
165 if (defined $exit_code && $exit_code == 0) {
166 $success = 1;
167 }
168
169 $update = $dbh->prepare("UPDATE imapsync SET returned_text = ?, success = ?, exit_status = ? WHERE id = ?");
Matthias Andreas Benkardb382b102021-01-02 15:32:21 +0100170 $update->bind_param( 1, ${stdout} );
Matthias Andreas Benkard12a57352021-12-28 18:02:04 +0100171 $update->bind_param( 2, ${success} );
172 $update->bind_param( 3, ${exit_status} );
173 $update->bind_param( 4, ${id} );
Matthias Andreas Benkardb382b102021-01-02 15:32:21 +0100174 $update->execute();
175 } catch {
Matthias Andreas Benkard12a57352021-12-28 18:02:04 +0100176 $update = $dbh->prepare("UPDATE imapsync SET returned_text = 'Could not start or finish imapsync', success = 0 WHERE id = ?");
Matthias Andreas Benkardb382b102021-01-02 15:32:21 +0100177 $update->bind_param( 1, ${id} );
178 $update->execute();
179 } finally {
180 $update = $dbh->prepare("UPDATE imapsync SET last_run = NOW(), is_running = 0 WHERE id = ?");
181 $update->bind_param( 1, ${id} );
182 $update->execute();
183 };
184
185
186}
187
188$sth->finish();
189$dbh->disconnect();
190
191$lockmgr->unlock($lock_file);