blob: 746b1d47a51f8819ea280dd884df67f22a729773 [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";
39$dsn = 'DBI:mysql:database=__DBNAME__;mysql_socket=/var/run/mysqld/mysqld.sock';
40$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}";
43$dbh = DBI->connect($dsn, '__DBUSER__', '__DBPASS__', {
44 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",
130 ($timeout1 gt "0" ? () : ('--timeout1', $timeout1)),
131 ($timeout2 gt "0" ? () : ('--timeout2', $timeout2)),
132 ($exclude eq "" ? () : ("--exclude", $exclude)),
133 ($subfolder2 eq "" ? () : ('--subfolder2', $subfolder2)),
134 ($maxage eq "0" ? () : ('--maxage', $maxage)),
135 ($maxbytespersecond eq "0" ? () : ('--maxbytespersecond', $maxbytespersecond)),
136 ($delete2duplicates ne "1" ? () : ('--delete2duplicates')),
137 ($subscribeall ne "1" ? () : ('--subscribeall')),
138 ($delete1 ne "1" ? () : ('--delete')),
139 ($delete2 ne "1" ? () : ('--delete2')),
140 ($automap ne "1" ? () : ('--automap')),
141 ($skipcrossduplicates ne "1" ? () : ('--skipcrossduplicates')),
142 (!defined($enc1) ? () : ($enc1)),
143 "--host1", $host1,
144 "--user1", $user1,
145 "--passfile1", $passfile1->filename,
146 "--port1", $port1,
147 "--host2", "localhost",
148 "--user2", $user2 . '*' . trim($master_user),
149 "--passfile2", $passfile2->filename,
150 '--no-modulesversion',
151 '--noreleasecheck'];
152
153 try {
154 $is_running = $dbh->prepare("UPDATE imapsync SET is_running = 1 WHERE id = ?");
155 $is_running->bind_param( 1, ${id} );
156 $is_running->execute();
157
158 run [@$generated_cmds, @$custom_params_ref], '&>', \my $stdout;
159
160 $update = $dbh->prepare("UPDATE imapsync SET returned_text = ? WHERE id = ?");
161 $update->bind_param( 1, ${stdout} );
162 $update->bind_param( 2, ${id} );
163 $update->execute();
164 } catch {
165 $update = $dbh->prepare("UPDATE imapsync SET returned_text = 'Could not start or finish imapsync' WHERE id = ?");
166 $update->bind_param( 1, ${id} );
167 $update->execute();
168 } finally {
169 $update = $dbh->prepare("UPDATE imapsync SET last_run = NOW(), is_running = 0 WHERE id = ?");
170 $update->bind_param( 1, ${id} );
171 $update->execute();
172 };
173
174
175}
176
177$sth->finish();
178$dbh->disconnect();
179
180$lockmgr->unlock($lock_file);