File Coverage

lib/Mail/Toaster/Setup.pm
Criterion Covered Total %
statement 185 1944 9.5
branch 68 1096 6.2
condition 9 285 3.1
subroutine 38 139 27.3
pod 11 126 8.7
total 311 3590 8.6


line stmt bran cond sub pod time code
1             package Mail::Toaster::Setup;
2 4     4   2018 use strict;
  4         6  
  4         99  
3 4     4   11 use warnings;
  4         4  
  4         138  
4              
5             our $VERSION = '5.54';
6              
7 4     4   13 use Carp;
  4         5  
  4         195  
8 4     4   14 use Config;
  4         5  
  4         132  
9 4     4   15 use Cwd;
  4         6  
  4         174  
10 4     4   2101 use Data::Dumper;
  4         17074  
  4         185  
11 4     4   407 use File::Copy;
  4         1850  
  4         160  
12 4     4   15 use File::Path;
  4         4  
  4         160  
13 4     4   379 use English qw( -no_match_vars );
  4         1191  
  4         20  
14 4     4   1589 use Params::Validate qw( :all );
  4         5841  
  4         510  
15 4     4   353 use Sys::Hostname;
  4         751  
  4         145  
16              
17 4     4   13 use lib 'lib';
  4         4  
  4         23  
18 4     4   647 use parent 'Mail::Toaster::Base';
  4         207  
  4         19  
19              
20             sub autorespond {
21 3     3 0 13 my $self = shift;
22 3         15 my %p = validate( @_, { $self->get_std_opts } );
23              
24 3 100       25 return $p{test_ok} if defined $p{test_ok}; # for testing
25              
26 1 50       2 my $ver = $self->conf->{install_autorespond} or do {
27 1         3 $self->audit( "autorespond install skipped (disabled)" );
28 1         4 return;
29             };
30              
31 0 0 0     0 if ( $OSNAME eq "freebsd" && $ver eq "port" ) {
32 0         0 $self->freebsd->install_port( "autorespond" );
33             }
34              
35 0         0 my $autorespond = $self->util->find_bin( "autorespond", fatal => 0, verbose => 0 );
36              
37             # return success if it is installed.
38 0 0 0     0 if ( $autorespond && -x $autorespond ) {
39 0         0 $self->audit( "autorespond: installed ok (exists)" );
40 0         0 return 1;
41             }
42              
43 0 0       0 if ( $ver eq "port" ) {
44 0         0 print
45             "autorespond: port install failed, attempting to install from source.\n";
46 0         0 $ver = "2.0.5";
47             }
48              
49 0         0 my @targets = ( 'make', 'make install' );
50              
51 0 0 0     0 if ( $OSNAME eq "darwin" || $OSNAME eq "freebsd" ) {
52 0         0 print "autorespond: applying strcasestr patch.\n";
53 0         0 my $sed = $self->util->find_bin( "sed", verbose => 0 );
54 0   0     0 my $prefix = $self->conf->{toaster_prefix} || "/usr/local";
55 0         0 $prefix =~ s/\//\\\//g;
56 0         0 @targets = (
57             "$sed -i '' 's/strcasestr/strcasestr2/g' autorespond.c",
58             "$sed -i '' 's/PREFIX=\$(DESTDIR)\\/usr/PREFIX=\$(DESTDIR)$prefix/g' Makefile",
59             'make', 'make install'
60             );
61             }
62              
63             $self->util->install_from_source(
64 0         0 package => "autorespond-$ver",
65             site => 'http://www.inter7.com',
66             url => '/devel',
67             targets => \@targets,
68             bintest => 'autorespond',
69             source_sub_dir => 'mail',
70             );
71              
72 0 0       0 if ( $self->util->find_bin( "autorespond", fatal => 0, verbose => 0, ) ) {
73 0         0 $self->audit( "autorespond: installed ok" );
74 0         0 return 1;
75             }
76              
77 0         0 return 0;
78             }
79              
80             sub clamav {
81 3     3 1 10 my $self = shift;
82 3         7 my %p = validate( @_, { $self->get_std_opts } );
83              
84 3 100       18 return $p{test_ok} if defined $p{test_ok}; # for testing
85              
86 1   50     2 my $prefix = $self->conf->{toaster_prefix} || "/usr/local";
87 1   50     3 my $confdir = $self->conf->{system_config_dir} || "/usr/local/etc";
88 1         2 my $share = "$prefix/share/clamav";
89 1   50     2 my $clamuser = $self->conf->{install_clamav_user} || "clamav";
90 1 50       1 my $ver = $self->conf->{install_clamav} or do {
91 1         2 $self->audit( "clamav: installing, skipping (disabled)" );
92 1         3 return;
93             };
94              
95 0         0 my $installed;
96              
97             # install via ports if selected
98 0 0 0     0 if ( $OSNAME eq "freebsd" && $ver eq "port" ) {
99 0         0 $self->freebsd->install_port( "clamav", flags => "BATCH=yes WITHOUT_LDAP=1");
100 0         0 return $self->clamav_post_install;
101             }
102              
103             # add the clamav user and group
104 0 0       0 unless ( getpwuid($clamuser) ) {
105 0         0 $self->group_add( 'clamav', '90' );
106 0         0 $self->user_add( $clamuser, 90, 90 );
107             }
108              
109 0 0       0 unless ( getpwnam($clamuser) ) {
110 0         0 print "User clamav user installation FAILED, I cannot continue!\n";
111 0         0 return 0;
112             }
113              
114             # install via ports if selected
115 0 0 0     0 if ( $OSNAME eq "darwin" && $ver eq "port" ) {
116 0 0       0 $self->darwin->install_port( "clamav" ) or return;
117 0         0 return $self->clamav_post_install;
118             }
119              
120             # port installs didn't work out, time to build from sources
121              
122             # set a default version of ClamAV if not provided
123 0 0       0 if ( $ver eq "1" ) { $ver = "0.97.8"; }; # latest as of 6/2013
  0         0  
124              
125             # download the sources, build, and install ClamAV
126             $self->util->install_from_source(
127             package => 'clamav-' . $ver,
128             site => 'http://' . $self->conf->{toaster_sf_mirror},
129 0         0 url => '/clamav',
130             targets => [ './configure', 'make', 'make install' ],
131             bintest => 'clamdscan',
132             source_sub_dir => 'mail',
133             );
134              
135 0 0       0 $self->util->find_bin( "clamdscan", fatal => 0 ) or
136             return $self->error( "clamav: install FAILED" );
137              
138 0         0 $self->audit( "clamav: installed ok" );
139              
140 0         0 return $self->clamav_post_install;
141             }
142              
143             sub clamav_post_install {
144 0     0 0 0 my $self = shift;
145 0         0 my %p = validate( @_, { $self->get_std_opts } );
146              
147 0 0       0 $self->clamav_update or return;
148 0 0       0 $self->clamav_perms or return;
149 0 0       0 $self->clamav_start or return;
150 0         0 return 1;
151             }
152              
153             sub clamav_perms {
154 0     0 0 0 my $self = shift;
155 0         0 my %p = validate( @_, { $self->get_std_opts } );
156              
157 0   0     0 my $prefix = $self->conf->{toaster_prefix} || "/usr/local";
158 0   0     0 my $confdir = $self->conf->{system_config_dir} || "/usr/local/etc";
159 0   0     0 my $clamuid = $self->conf->{install_clamav_user} || "clamav";
160 0         0 my $share = "$prefix/share/clamav";
161              
162 0         0 foreach my $file ( $share, "$share/daily.cvd", "$share/main.cvd",
163             "$share/viruses.db", "$share/viruses.db2", "/var/log/clamav/freshclam.log", ) {
164              
165 0 0       0 if ( -e $file ) {
166 0         0 print "setting the ownership of $file to $clamuid.\n";
167 0         0 $self->util->chown( $file, uid => $clamuid, gid => 'clamav' );
168             };
169             }
170              
171 0 0       0 $self->util->syscmd( "pw user mod clamav -G qmail" )
172             or return $self->error( "failed to add clamav to the qmail group" );
173              
174 0         0 return 1;
175             }
176              
177             sub clamav_start {
178             # get ClamAV running
179 0     0 0 0 my $self = shift;
180 0         0 my %p = validate( @_, { $self->get_std_opts } );
181              
182 0 0       0 if ( $self->util->is_process_running('clamd') ) {
183 0         0 $self->audit( "clamav: starting up, ok (already running)" );
184             }
185              
186 0         0 print "Starting up ClamAV...\n";
187              
188 0 0       0 if ( $OSNAME ne "freebsd" ) {
189 0         0 $self->util->_incomplete_feature( {
190             mess => "start up ClamAV on $OSNAME",
191             action =>
192             'You will need to start up ClamAV yourself and make sure it is configured to launch at boot time.',
193             }
194             );
195 0         0 return;
196             };
197              
198 0         0 $self->freebsd->conf_check(
199             check => "clamav_clamd_enable",
200             line => 'clamav_clamd_enable="YES"',
201             );
202              
203 0         0 $self->freebsd->conf_check(
204             check => "clamav_freshclam_enable",
205             line => 'clamav_freshclam_enable="YES"',
206             );
207              
208 0         0 print "(Re)starting ClamAV's clamd...";
209 0         0 my $start = "/usr/local/etc/rc.d/clamav-freshclam";
210 0 0       0 $start = "$start.sh" if ! -x $start;
211              
212 0 0       0 if ( -x $start ) {
213 0         0 system "$start restart";
214 0         0 print "done.\n";
215             }
216             else {
217 0         0 print
218             "ERROR: I could not find the startup (rc.d) file for clamAV!\n";
219             }
220              
221 0         0 print "(Re)starting ClamAV's freshclam...";
222 0         0 $start = "/usr/local/etc/rc.d/clamav-clamd";
223 0 0       0 $start = "$start.sh" if ! -x $start;
224 0         0 system "$start restart";
225              
226 0 0       0 if ( $self->util->is_process_running('clamd', verbose=>0) ) {
227 0         0 $self->audit( "clamav: starting up, ok" );
228             }
229              
230             # These are no longer required as the FreeBSD ports now installs
231             # startup files of its own.
232 0         0 foreach ( qw/ clamav.sh freshclam.sh / ) {
233 0 0       0 unlink "/usr/local/etc/rc.d/$_" if -e "/usr/local/etc/rc.d/$_";
234             };
235              
236 0         0 return 1;
237             }
238              
239             sub clamav_update {
240 0     0 0 0 my $self = shift;
241 0         0 my %p = validate( @_, { $self->get_std_opts } );
242              
243             # set up freshclam (keeps virus databases updated)
244 0         0 my $logfile = "/var/log/clamav/freshclam.log";
245 0 0       0 unless ( -e $logfile ) {
246 0         0 $self->util->syscmd( "touch $logfile", verbose=>0 );
247 0         0 $self->util->chmod( file => $logfile, mode => '0644', verbose=>0 );
248 0         0 $self->clamav_perms( verbose=>0 );
249             }
250              
251 0 0       0 my $freshclam = $self->util->find_bin( "freshclam", verbose=>0 )
252             or return $self->error( "couldn't find freshclam!", fatal=>0);
253              
254 0         0 $self->audit("updating ClamAV database with freshclam");
255 0         0 $self->util->syscmd( "$freshclam", verbose => 0, fatal => 0 );
256 0         0 return 1;
257             }
258              
259             sub config {
260 2     2 1 455 require Mail::Toaster::Setup::Config;
261 2         11 return Mail::Toaster::Setup::Config->new;
262             };
263              
264             sub courier_imap {
265 3     3 0 12 my $self = shift;
266 3         7 my %p = validate( @_, { $self->get_std_opts } );
267              
268 3 100       19 return $p{test_ok} if defined $p{test_ok};
269              
270 1 50       2 my $ver = $self->conf->{install_courier_imap} or do {
271 1         2 $self->audit( "courier: installing, skipping (disabled)" );
272 1 50       5 $self->courier_startup_freebsd() if $OSNAME eq 'freebsd'; # enable startup
273 1         3 return;
274             };
275              
276 0         0 $self->audit("courier $ver is selected" );
277              
278 0 0 0     0 if ( $OSNAME eq "freebsd" && $ver eq "port" ) {
    0          
279 0         0 $self->audit("using courier from FreeBSD ports" );
280 0         0 $self->courier_authlib;
281 0         0 $self->courier_imap_freebsd;
282 0         0 $self->courier_startup;
283 0 0       0 return 1 if $self->freebsd->is_port_installed( "courier-imap", verbose=>0);
284             }
285             elsif ( $OSNAME eq "darwin" ) {
286 0         0 return $self->darwin->install_port( "courier-imap", );
287             }
288              
289             # if a specific version has been requested, install it from sources
290             # but first, a default for users who didn't edit toaster-watcher.conf
291 0 0       0 $ver = "4.8.0" if ( $ver eq "port" );
292              
293 0         0 my $site = "http://" . $self->conf->{toaster_sf_mirror};
294 0   0     0 my $confdir = $self->conf->{system_config_dir} || "/usr/local/etc";
295 0   0     0 my $prefix = $self->conf->{toaster_prefix} || "/usr/local";
296              
297 0         0 $ENV{"HAVE_OPEN_SMTP_RELAY"} = 1; # circumvent bug in courier
298              
299 0         0 my $conf_args = "--prefix=$prefix --exec-prefix=$prefix --without-authldap --without-authshadow --with-authvchkpw --sysconfdir=/usr/local/etc/courier-imap --datadir=$prefix/share/courier-imap --libexecdir=$prefix/libexec/courier-imap --enable-workarounds-for-imap-client-bugs --disable-root-check --without-authdaemon";
300              
301 0         0 print "./configure $conf_args\n";
302 0   0     0 my $make = $self->util->find_bin( "gmake", verbose=>0, fatal=>0 ) ||
303             $self->util->find_bin( "make", verbose=>0);
304 0         0 my @targets = ( "./configure " . $conf_args, $make, "$make install" );
305              
306 0         0 $self->util->install_from_source(
307             package => "courier-imap-$ver",
308             site => $site,
309             url => "/courier",
310             targets => \@targets,
311             bintest => "imapd",
312             source_sub_dir => 'mail',
313             );
314              
315 0         0 $self->courier_startup();
316             }
317              
318             sub courier_imap_freebsd {
319 0     0 0 0 my $self = shift;
320              
321             # my @defs = "WITH_VPOPMAIL=1";
322             # push @defs, "WITHOUT_AUTHDAEMON=1";
323             # push @defs, "WITH_CRAM=1";
324             # push @defs, "AUTHMOD=authvchkpw";
325              
326 0         0 $self->freebsd->install_port( "courier-imap",
327             #flags => join( ",", @defs ),
328             options => "#\n# This file was generated by mail-toaster
329             # No user-servicable parts inside!
330             # Options for courier-imap-4.1.1,1
331             _OPTIONS_READ=courier-imap-4.1.1,1
332             WITH_OPENSSL=true
333             WITHOUT_FAM=true
334             WITHOUT_DRAC=true
335             WITHOUT_TRASHQUOTA=true
336             WITHOUT_GDBM=true
337             WITHOUT_IPV6=true
338             WITHOUT_AUTH_LDAP=true
339             WITHOUT_AUTH_MYSQL=true
340             WITHOUT_AUTH_PGSQL=true
341             WITHOUT_AUTH_USERDB=true
342             WITH_AUTH_VCHKPW=true",
343             );
344             }
345              
346             sub courier_authlib {
347 0     0 0 0 my $self = shift;
348 0         0 my %p = validate( @_, { $self->get_std_opts } );
349              
350 0   0     0 my $prefix = $self->conf->{toaster_prefix} || "/usr/local";
351 0   0     0 my $confdir = $self->conf->{system_config_dir} || "/usr/local/etc";
352              
353 0 0       0 if ( $OSNAME ne "freebsd" ) {
354 0         0 print "courier-authlib build support is not available for $OSNAME yet.\n";
355 0         0 return 0;
356             };
357              
358 0 0       0 if ( ! $self->freebsd->is_port_installed( "courier-authlib" ) ) {
359              
360 0         0 $self->freebsd->install_port( "courier-authlib",
361             options => "# Options for courier-authlib-0.65.0
362             _OPTIONS_READ=courier-authlib-0.65.0
363             _FILE_COMPLETE_OPTIONS_LIST=AUTH_LDAP AUTH_MYSQL AUTH_PGSQL AUTH_USERDB AUTH_VCHKPW GDBM
364             OPTIONS_FILE_UNSET+=AUTH_LDAP
365             OPTIONS_FILE_UNSET+=AUTH_MYSQL
366             OPTIONS_FILE_UNSET+=AUTH_PGSQL
367             OPTIONS_FILE_UNSET+=AUTH_USERDB
368             OPTIONS_FILE_SET+=AUTH_VCHKPW
369             OPTIONS_FILE_UNSET+=GDBM
370             ",
371             );
372             }
373              
374 0         0 $self->freebsd->install_port( "courier-authlib-vchkpw",
375             flags => "AUTHMOD=authvchkpw",
376             );
377              
378             # install a default authdaemonrc
379 0         0 my $authrc = "$confdir/authlib/authdaemonrc";
380              
381 0 0       0 if ( ! -e $authrc ) {
382 0 0       0 if ( -e "$authrc.dist" ) {
383 0         0 print "installing default authdaemonrc.\n";
384 0         0 copy("$authrc.dist", $authrc);
385             }
386             };
387              
388 0 0       0 if ( `grep 'authmodulelist=' $authrc | grep ldap` ) {
389 0         0 $self->config->apply_tweaks(
390             file => $authrc,
391             changes => [
392             { search => q{authmodulelist="authuserdb authvchkpw authpam authldap authmysql authpgsql"},
393             replace => q{authmodulelist="authvchkpw"},
394             },
395             ],
396             );
397 0         0 $self->audit( "courier_authlib: fixed up $authrc" );
398             }
399              
400             $self->freebsd->conf_check(
401 0         0 check => "courier_authdaemond_enable",
402             line => "courier_authdaemond_enable=\"YES\"",
403             );
404              
405 0 0       0 if ( ! -e "/var/run/authdaemond/pid" ) {
406 0         0 my $start = "$prefix/etc/rc.d/courier-authdaemond";
407 0         0 foreach ( $start, "$start.sh" ) {
408 0 0       0 $self->util->syscmd( "$_ start", verbose=>0) if -x $_;
409             };
410             };
411 0         0 return 1;
412             }
413              
414             sub courier_ssl {
415 0     0 0 0 my $self = shift;
416              
417 0   0     0 my $confdir = $self->conf->{system_config_dir} || "/usr/local/etc";
418 0   0     0 my $prefix = $self->conf->{toaster_prefix} || "/usr/local";
419 0         0 my $share = "$prefix/share/courier-imap";
420              
421             # apply ssl_ values from t-w.conf to courier's .cnf files
422 0 0 0     0 if ( ! -e "$share/pop3d.pem" || ! -e "$share/imapd.pem" ) {
423 0         0 my $pop3d_ssl_conf = "$confdir/courier-imap/pop3d.cnf";
424 0         0 my $imapd_ssl_conf = "$confdir/courier-imap/imapd.cnf";
425              
426 0   0     0 my $common_name = $self->conf->{ssl_common_name} || $self->conf->{toaster_hostname};
427 0         0 my $org = $self->conf->{ssl_organization};
428 0         0 my $locality = $self->conf->{ssl_locality};
429 0         0 my $state = $self->conf->{ssl_state};
430 0         0 my $country = $self->conf->{ssl_country};
431              
432 0         0 my $sed_command = "sed -i .bak -e 's/US/$country/' ";
433 0         0 $sed_command .= "-e 's/NY/$state/' ";
434 0         0 $sed_command .= "-e 's/New York/$locality/' ";
435 0         0 $sed_command .= "-e 's/Courier Mail Server/$org/' ";
436 0         0 $sed_command .= "-e 's/localhost/$common_name/' ";
437              
438 0         0 print "$sed_command\n";
439 0         0 system "$sed_command $pop3d_ssl_conf $imapd_ssl_conf";
440             };
441              
442             # use the toaster generated cert, if available
443 0         0 my $crt = "/usr/local/openssl/certs/server.pem";
444 0         0 foreach my $courier_pem ( "$share/pop3d.pem", "$share/imapd.pem" ) {
445 0 0 0     0 copy( $crt, $courier_pem ) if ( -f $crt && ! -e $courier_pem );
446             };
447              
448             # generate self-signed SSL certificates for pop3/imap
449 0 0       0 if ( ! -e "$share/pop3d.pem" ) {
450 0         0 chdir $share;
451 0         0 $self->util->syscmd( "./mkpop3dcert", verbose => 0 );
452             }
453              
454 0 0       0 if ( !-e "$share/imapd.pem" ) {
455 0         0 chdir $share;
456 0         0 $self->util->syscmd( "./mkimapdcert", verbose => 0 );
457             }
458             };
459              
460             sub courier_startup {
461              
462 0     0 0 0 my $self = shift;
463 0         0 my %p = validate( @_, { $self->get_std_opts } );
464              
465 0   0     0 my $prefix = $self->conf->{toaster_prefix} || "/usr/local";
466 0         0 my $ver = $self->conf->{install_courier_imap};
467 0   0     0 my $confdir = $self->conf->{system_config_dir} || "/usr/local/etc";
468              
469 0 0       0 chdir("$confdir/courier-imap") or
470             return $self->error( "could not chdir $confdir/courier-imap.");
471              
472 0 0       0 copy( "pop3d.cnf.dist", "pop3d.cnf" ) if ( !-e "pop3d.cnf" );
473 0 0       0 copy( "pop3d.dist", "pop3d" ) if ( !-e "pop3d" );
474 0 0       0 copy( "pop3d-ssl.dist", "pop3d-ssl" ) if ( !-e "pop3d-ssl" );
475 0 0       0 copy( "imapd.cnf.dist", "imapd.cnf" ) if ( !-e "imapd.cnf" );
476 0 0       0 copy( "imapd.dist", "imapd" ) if ( !-e "imapd" );
477 0 0       0 copy( "imapd-ssl.dist", "imapd-ssl" ) if ( !-e "imapd-ssl" );
478 0 0       0 copy( "quotawarnmsg.example", "quotawarnmsg" ) if ( !-e "quotawarnmsg" );
479              
480 0         0 $self->courier_ssl();
481              
482 0 0 0     0 if ( $OSNAME eq "freebsd" && $ver eq "port" ) {
483 0         0 $self->courier_startup_freebsd();
484             }
485             else {
486 0         0 my $libe = "$prefix/libexec/courier-imap";
487 0 0       0 if ( -e "$libe/imapd.rc" ) {
488 0         0 print "creating symlinks in /usr/local/sbin for courier daemons\n";
489 0         0 symlink( "$libe/imapd.rc", "$prefix/sbin/imap" );
490 0         0 symlink( "$libe/pop3d.rc", "$prefix/sbin/pop3" );
491 0         0 symlink( "$libe/imapd-ssl.rc", "$prefix/sbin/imapssl" );
492 0         0 symlink( "$libe/pop3d-ssl.rc", "$prefix/sbin/pop3ssl" );
493             }
494             else {
495 0         0 print
496             "FAILURE: sorry, I can't find the courier rc files on $OSNAME.\n";
497             }
498             }
499              
500 0         0 $self->courier_authlib();
501              
502 0 0       0 unless ( -e "/var/run/imapd-ssl.pid" ) {
503 0 0       0 $self->util->syscmd( "$prefix/sbin/imapssl start", verbose=>0 )
504             if -x "$prefix/sbin/imapssl";
505             }
506              
507 0 0       0 unless ( -e "/var/run/imapd.pid" ) {
508 0 0       0 $self->util->syscmd( "$prefix/sbin/imap start", verbose=>0 )
509             if -x "$prefix/sbin/imapssl";
510             }
511              
512 0 0       0 unless ( -e "/var/run/pop3d-ssl.pid" ) {
513 0 0       0 $self->util->syscmd( "$prefix/sbin/pop3ssl start", verbose=>0 )
514             if -x "$prefix/sbin/pop3ssl";
515             }
516              
517 0 0       0 if ( $self->conf->{pop3_daemon} eq "courier" ) {
518 0 0       0 if ( !-e "/var/run/pop3d.pid" ) {
519 0 0       0 $self->util->syscmd( "$prefix/sbin/pop3 start", verbose=>0 )
520             if -x "$prefix/sbin/pop3";
521             }
522             }
523             }
524              
525             sub courier_startup_freebsd {
526 0     0 0 0 my $self = shift;
527              
528 0   0     0 my $prefix = $self->conf->{toaster_prefix} || "/usr/local";
529 0   0     0 my $confdir = $self->conf->{system_config_dir} || "/usr/local/etc";
530              
531 0 0       0 return 1 if ! $self->freebsd->is_port_installed( 'courier-imap' );
532              
533             # cleanup stale links, created long ago when rc.d files had .sh endings
534 0         0 foreach ( qw/ imap imapssl pop3 pop3ssl / ) {
535 0 0       0 if ( -e "$prefix/sbin/$_" ) {
536 0 0       0 readlink "$prefix/sbin/$_" or unlink "$prefix/sbin/$_";
537             };
538             };
539              
540 0 0       0 if ( ! -e "$prefix/sbin/imap" ) {
541 0         0 $self->audit( "setting up startup file shortcuts for daemons");
542 0         0 symlink( "$confdir/rc.d/courier-imap-imapd", "$prefix/sbin/imap" );
543 0         0 symlink( "$confdir/rc.d/courier-imap-pop3d", "$prefix/sbin/pop3" );
544 0         0 symlink( "$confdir/rc.d/courier-imap-imapd-ssl", "$prefix/sbin/imapssl" );
545 0         0 symlink( "$confdir/rc.d/courier-imap-pop3d-ssl", "$prefix/sbin/pop3ssl" );
546             }
547              
548 0 0       0 my $start = $self->conf->{install_courier_imap} ? 'YES' : 'NO';
549              
550 0         0 $self->freebsd->conf_check(
551             check => "courier_imap_imapd_enable",
552             line => "courier_imap_imapd_enable=\"$start\"",
553             );
554              
555 0         0 $self->freebsd->conf_check(
556             check => "courier_imap_imapdssl_enable",
557             line => "courier_imap_imapdssl_enable=\"$start\"",
558             );
559              
560 0         0 $self->freebsd->conf_check(
561             check => "courier_imap_imapd_ssl_enable",
562             line => "courier_imap_imapd_ssl_enable=\"$start\"",
563             );
564              
565 0         0 $self->freebsd->conf_check(
566             check => "courier_imap_pop3dssl_enable",
567             line => "courier_imap_pop3dssl_enable=\"$start\"",
568             );
569              
570 0         0 $self->freebsd->conf_check(
571             check => "courier_imap_pop3d_ssl_enable",
572             line => "courier_imap_pop3d_ssl_enable=\"$start\"",
573             );
574              
575 0 0       0 if ( $self->conf->{pop3_daemon} eq "courier" ) {
576 0         0 $self->freebsd->conf_check(
577             check => "courier_imap_pop3d_enable",
578             line => "courier_imap_pop3d_enable=\"YES\"",
579             );
580             }
581             else {
582 0         0 $self->freebsd->conf_check(
583             check => "courier_imap_pop3d_enable",
584             line => "courier_imap_pop3d_enable=\"NO\"",
585             );
586             };
587             };
588              
589             sub cronolog {
590 3     3 0 11 my $self = shift;
591 3         8 my %p = validate( @_, { $self->get_std_opts } );
592              
593 3 100       17 return $p{test_ok} if defined $p{test_ok}; # for testing
594              
595 1 50       3 my $ver = $self->conf->{install_cronolog} or do {
596 1         3 $self->audit( "cronolog: skipping install (disabled)");
597 1         3 return;
598             };
599              
600 0 0 0     0 if ( $OSNAME eq "freebsd" && $ver eq "port" ) {
601 0         0 return $self->cronolog_freebsd();
602             }
603              
604 0 0       0 if ( $self->util->find_bin( "cronolog", fatal => 0 ) ) {
605 0         0 $self->audit( "cronolog: install cronolog, ok (exists)",verbose=>1 );
606 0         0 return 2;
607             }
608              
609 0         0 $self->audit( "attempting cronolog install from source");
610              
611 0 0       0 if ( $ver eq "port" ) { $ver = "1.6.2" }; # a fallback version
  0         0  
612              
613 0         0 $self->util->install_from_source(
614             package => "cronolog-$ver",
615             site => 'http://www.cronolog.org',
616             url => '/download',
617             targets => [ './configure', 'make', 'make install' ],
618             bintest => 'cronolog',
619             );
620              
621 0 0       0 $self->util->find_bin( "cronolog" ) or return;
622              
623 0         0 $self->audit( "cronolog: install cronolog, ok" );
624 0         0 return 1;
625             }
626              
627             sub cronolog_freebsd {
628 0     0 0 0 my $self = shift;
629 0         0 $self->freebsd->install_package('cronolog');
630 0 0       0 return 1 if $self->freebsd->is_port_installed('cronolog');
631 0         0 return $self->freebsd->install_port( "cronolog",
632             fatal => 0,
633             options => "# This file generated by mail-toaster
634             # Options for cronolog-1.6.2_4
635             _OPTIONS_READ=cronolog-1.6.2_4
636             _FILE_COMPLETE_OPTIONS_LIST=SETUID_PATCH
637             OPTIONS_FILE_UNSET+=SETUID_PATCH\n",
638             );
639             };
640              
641             sub daemontools {
642 3     3 1 24 my $self = shift;
643 3         7 my %p = validate( @_, { $self->get_std_opts } );
644              
645 3 100       18 return $p{test_ok} if defined $p{test_ok};
646              
647 1 50       4 my $ver = $self->conf->{install_daemontools} or do {
648 1         2 $self->audit( "daemontools: installing, (disabled)" );
649 1         3 return;
650             };
651              
652 0 0       0 $self->daemontools_freebsd() if $OSNAME eq "freebsd";
653              
654 0 0 0     0 if ( $OSNAME eq "darwin" && $ver eq "port" ) {
655 0         0 $self->darwin->install_port( "daemontools" );
656              
657 0         0 print
658             "\a\n\nWARNING: there is a bug in the OS 10.4 kernel that requires daemontools to be built with a special tweak. This must be done once. You will be prompted to install daemontools now. If you haven't already allowed this script to build daemontools from source, please do so now!\n\n";
659 0         0 sleep 2;
660             }
661              
662             # see if the svscan binary is already installed
663 0 0       0 $self->util->find_bin( "svscan", fatal => 0, verbose => 0 ) and do {
664 0         0 $self->audit( "daemontools: installing, ok (exists)" );
665 0         0 return 1;
666             };
667              
668 0         0 $self->daemontools_src();
669             };
670              
671             sub daemontools_src {
672 0     0 0 0 my $self = shift;
673              
674 0         0 my $ver = $self->conf->{install_daemontools};
675 0 0       0 $ver = "0.76" if $ver eq "port";
676              
677 0         0 my $package = "daemontools-$ver";
678 0   0     0 my $prefix = $self->conf->{toaster_prefix} || "/usr/local";
679              
680 0         0 my @targets = ('package/install');
681 0         0 my @patches;
682 0         0 my $patch_args = ""; # cannot be undef
683              
684 0 0       0 if ( $OSNAME eq "darwin" ) {
    0          
    0          
685 0         0 print "daemontools: applying fixups for Darwin.\n";
686 0         0 @targets = (
687             "echo cc -Wl,-x > src/conf-ld",
688             "echo $prefix/bin > src/home",
689             "echo x >> src/trypoll.c",
690             "cd src",
691             "make",
692             );
693             }
694             elsif ( $OSNAME eq "linux" ) {
695 0         0 print "daemontools: applying fixups for Linux.\n";
696 0         0 @patches = ('daemontools-0.76.errno.patch');
697 0         0 $patch_args = "-p0";
698             }
699             elsif ( $OSNAME eq "freebsd" ) {
700             @targets = (
701 0         0 'echo "' . $self->conf->{toaster_prefix} . '" > src/home',
702             "cd src", "make",
703             );
704             }
705              
706             $self->util->install_from_source(
707             package => $package,
708             site => 'http://cr.yp.to',
709             url => '/daemontools',
710             targets => \@targets,
711             patches => \@patches,
712             patch_args => $patch_args,
713 0         0 patch_url => $self->conf->{toaster_dl_site}.$self->conf->{toaster_dl_url}.'/patches',
714             bintest => 'svscan',
715             );
716              
717 0 0       0 if ( $OSNAME =~ /darwin|freebsd/i ) {
718              
719             # manually install the daemontools binaries in $prefix/local/bin
720 0         0 chdir $self->conf->{toaster_src_dir}."/admin/$package";
721              
722 0         0 foreach ( $self->util->file_read( "package/commands" ) ) {
723 0         0 my $install = $self->util->find_bin( 'install' );
724 0         0 $self->util->syscmd( "$install src/$_ $prefix/bin", verbose=>0 );
725             }
726             }
727              
728 0         0 return 1;
729             }
730              
731             sub daemontools_freebsd {
732 0     0 0 0 my $self = shift;
733 0         0 return $self->freebsd->install_port( "daemontools",
734             options => '# This file is generated by Mail Toaster
735             # Options for daemontools-0.76_16
736             _OPTIONS_READ=daemontools-0.76_16
737             _FILE_COMPLETE_OPTIONS_LIST=MAN SIGQ12 TESTS S_EARLY S_NORMAL
738             OPTIONS_FILE_SET+=MAN
739             OPTIONS_FILE_UNSET+=SIGQ12
740             OPTIONS_FILE_SET+=TESTS
741             OPTIONS_FILE_UNSET+=S_EARLY
742             OPTIONS_FILE_SET+=S_NORMAL
743             ',
744             fatal => 0,
745             );
746             };
747              
748             sub daemontools_test {
749 0     0 0 0 my $self = shift;
750              
751 0         0 print "checking daemontools binaries...\n";
752 0         0 my @bins = qw{ multilog softlimit setuidgid supervise svok svscan tai64nlocal };
753 0         0 foreach my $test ( @bins ) {
754 0         0 my $bin = $self->util->find_bin( $test, fatal => 0, verbose=>0);
755 0         0 $self->test->pretty(" $test", -x $bin );
756             };
757              
758 0         0 return 1;
759             }
760              
761             sub dependencies {
762 2     2 1 2 my $self = shift;
763 2         7 my %p = validate( @_, { $self->get_std_opts } );
764              
765 2 50       16 return $p{test_ok} if defined $p{test_ok}; # for testing
766              
767 0         0 my $qmaildir = $self->qmail->get_qmail_dir;
768              
769 0 0       0 if ( $OSNAME eq "freebsd" ) {
    0          
770 0         0 $self->dependencies_freebsd();
771             }
772             elsif ( $OSNAME eq "darwin" ) {
773 0         0 my @dports =
774             qw/ cronolog gdbm gmake ucspi-tcp daemontools DarwinPortsStartup /;
775              
776 0 0       0 push @dports, "maildrop" if $self->conf->{install_maildrop};
777 0 0       0 push @dports, "openldap" if $self->conf->{install_openldap_client};
778 0 0       0 push @dports, "gnupg" if $self->conf->{install_gnupg};
779              
780 0         0 foreach (@dports) { $self->darwin->install_port( $_ ) }
  0         0  
781             }
782             else {
783 0         0 $self->dependencies_other();
784             };
785              
786 0         0 $self->util->install_module( "Params::Validate" );
787 0         0 $self->util->install_module( "IO::Compress" );
788 0         0 $self->util->install_module( "Compress::Raw::Zlib" );
789             # $self->util->install_module( "Crypt::PasswdMD5" );
790 0         0 $self->util->install_module( "Net::DNS" );
791 0 0       0 $self->util->install_module( "Quota", fatal => 0 ) if $self->conf->{install_quota_tools};
792 0         0 $self->util->install_module( "Date::Format", port => "p5-TimeDate");
793 0         0 $self->util->install_module( "Date::Parse" );
794 0         0 $self->util->install_module( "Mail::Send", port => "p5-Mail-Tools");
795 0 0       0 $self->util->install_module( "Qmail::Deliverable") if $self->conf->{install_qmail_deliverable};
796              
797 0 0       0 if ( ! -x "$qmaildir/bin/qmail-queue" ) {
798 0         0 $self->conf->{qmail_chk_usr_patch} = 0;
799 0         0 $self->qmail->netqmail_virgin();
800             }
801              
802 0         0 $self->daemontools();
803 0         0 $self->autorespond();
804             }
805              
806             sub dependencies_freebsd {
807 0     0 0 0 my $self = shift;
808 0   0     0 my $package = $self->conf->{package_install_method} || "packages";
809              
810 0         0 $self->periodic_conf; # create /etc/periodic.conf
811 0         0 $self->gmake_freebsd;
812 0         0 $self->openssl_install;
813 0 0       0 $self->stunnel if $self->conf->{pop3_ssl_daemon} eq "qpop3d";
814 0         0 $self->ucspi_tcp_freebsd;
815 0         0 $self->cronolog_freebsd;
816              
817 0         0 my @to_install = (
818             { port => "p5-Params-Validate" },
819             { port => "p5-Net-DNS" },
820             );
821 0 0       0 push @to_install, { port => "setquota" } if $self->conf->{install_quota_tools};
822 0         0 push @to_install, {
823             port => 'gdbm',
824             options => "# This file generated by Mail::Toaster
825             # Options for gdbm-1.10
826             _OPTIONS_READ=gdbm-1.10
827             _FILE_COMPLETE_OPTIONS_LIST=COMPAT NLS
828             OPTIONS_FILE_UNSET+=COMPAT
829             OPTIONS_FILE_UNSET+=NLS\n",
830             };
831             push @to_install, { port => 'openldap23-client',
832             check => "openldap-client",
833             category => 'net',
834 0 0       0 } if $self->conf->{install_openldap_client};
835 0         0 push @to_install, { port => "qmail",
836             flags => "BATCH=yes",
837             options => "#\n# Installed by Mail::Toaster
838             # Options for qmail-1.03_7\n_OPTIONS_READ=qmail-1.03_7",
839             };
840 0         0 push @to_install, { port => "qmailanalog", fatal => 0 };
841             push @to_install, { port => "qmail-notify", fatal => 0 }
842 0 0       0 if $self->conf->{install_qmail_notify};
843              
844             # if package method is selected, try it
845 0 0       0 if ( $package eq "packages" ) {
846 0         0 foreach ( @to_install ) {
847 0   0     0 my $port = $_->{port} || $_->{name};
848 0         0 $self->freebsd->install_package( $port, fatal => 0 );
849             };
850             }
851              
852 0         0 foreach my $port (@to_install) {
853             $self->freebsd->install_port( $port->{port},
854             defined $port->{flags} ? (flags => $port->{flags} ) : (),
855             defined $port->{options} ? (options => $port->{options} ) : (),
856             defined $port->{check} ? (check => $port->{check} ) : (),
857             defined $port->{fatal} ? (fatal => $port->{fatal} ) : (),
858 0 0       0 defined $port->{category}? (category=> $port->{category}) : (),
    0          
    0          
    0          
    0          
859             );
860             }
861             };
862              
863             sub dependencies_other {
864 0     0 0 0 my $self = shift;
865 0         0 print "no ports for $OSNAME, installing from sources.\n";
866              
867 0 0       0 if ( $OSNAME eq "linux" ) {
868 0         0 my $vpopdir = $self->vpopmail->get_vpop_dir;
869 0         0 $self->qmail->install_qmail_groups_users;
870              
871 0         0 $self->util->syscmd( "groupadd -g 89 vchkpw" );
872 0         0 $self->util->syscmd( "useradd -g vchkpw -d $vpopdir vpopmail" );
873 0         0 $self->util->syscmd( "groupadd clamav" );
874 0         0 $self->util->syscmd( "useradd -g clamav clamav" );
875             }
876              
877 0         0 my @progs = qw(gmake expect cronolog autorespond );
878 0 0       0 push @progs, "setquota" if $self->conf->{install_quota_tools};
879 0 0       0 push @progs, "gnupg" if $self->conf->{install_gnupg};
880              
881 0         0 foreach (@progs) {
882 0 0       0 if ( $self->util->find_bin( $_, verbose=>0,fatal=>0 ) ) {
883 0         0 $self->audit( "checking for $_, ok" );
884             }
885             else {
886 0         0 print "$_ not installed. FAILED, please install manually.\n";
887             }
888             }
889             }
890              
891             sub djbdns {
892 3     3 1 10 my $self = shift;
893 3         7 my %p = validate( @_, { $self->get_std_opts } );
894              
895 3 100       16 return $p{test_ok} if defined $p{test_ok}; # for testing
896              
897 1 50       2 if ( ! $self->conf->{install_djbdns} ) {
898 1         3 $self->audit( "djbdns: installing, skipping (disabled)" );
899 1         3 return;
900             };
901              
902 0         0 $self->daemontools();
903 0         0 $self->ucspi_tcp();
904              
905 0 0       0 return $self->audit( "djbdns: installing djbdns, ok (already installed)" )
906             if $self->util->find_bin( 'tinydns', fatal => 0 );
907              
908 0 0       0 if ( $OSNAME eq "freebsd" ) {
909 0         0 $self->djbdns_freebsd();
910              
911 0 0       0 return $self->audit( "djbdns: installing djbdns, ok" )
912             if $self->util->find_bin( 'tinydns', fatal => 0 );
913             }
914              
915 0         0 return $self->djbdns_src();
916             };
917              
918             sub djbdns_src {
919 0     0 0 0 my $self = shift;
920              
921 0         0 my @targets = ( 'make', 'make setup check' );
922              
923 0 0       0 if ( $OSNAME eq "linux" ) {
924 0         0 unshift @targets,
925             'echo gcc -O2 -include /usr/include/errno.h > conf-cc';
926             }
927              
928             $self->util->install_from_source(
929 0         0 package => "djbdns-1.05",
930             site => 'http://cr.yp.to',
931             url => '/djbdns',
932             targets => \@targets,
933             bintest => 'tinydns',
934             );
935             }
936              
937             sub djbdns_freebsd {
938 0     0 0 0 my $self = shift;
939 0         0 $self->freebsd->install_port( "djbdns",
940             options => "#\n
941             # Options for djbdns-1.05_13
942             _OPTIONS_READ=djbdns-1.05_13
943             WITHOUT_DUMPCACHE=true
944             WITHOUT_IPV6=true
945             WITHOUT_IGNOREIP=true
946             WITHOUT_JUMBO=true
947             WITH_MAN=true
948             WITHOUT_PERSISTENT_MMAP=true
949             WITHOUT_SRV=true\n",
950             );
951             };
952              
953             sub docs {
954 0     0 0 0 my $self = shift;
955              
956 0         0 my $cmd;
957              
958 0 0 0     0 if ( !-f "README" && !-f "lib/toaster.conf.pod" ) {
959 0         0 print <<"EO_NOT_IN_DIST_ERR";
960              
961             ERROR: This setup target can only be run in the Mail::Toaster distibution directory!
962              
963             Try switching into there and trying again.
964             EO_NOT_IN_DIST_ERR
965              
966 0         0 return;
967             };
968              
969             # convert pod to text files
970 0         0 my $pod2text = $self->util->find_bin( "pod2text", verbose=>0);
971              
972 0         0 $self->util->syscmd("$pod2text bin/toaster_setup.pl > README", verbose=>0);
973 0         0 $self->util->syscmd("$pod2text lib/toaster.conf.pod > doc/toaster.conf", verbose=>0);
974 0         0 $self->util->syscmd("$pod2text lib/toaster-watcher.conf.pod > doc/toaster-watcher.conf", verbose=>0);
975              
976              
977             # convert pod docs to HTML pages for the web site
978              
979 0         0 my $pod2html = $self->util->find_bin("pod2html", verbose=>0);
980              
981 0         0 $self->util->syscmd( "$pod2html --title='toaster.conf' lib/toaster.conf.pod > doc/toaster.conf.html",
982             verbose=>0, );
983 0         0 $self->util->syscmd( "$pod2html --title='watcher.conf' lib/toaster-watcher.conf.pod > doc/toaster-watcher.conf.html",
984             verbose=>0, );
985 0         0 $self->util->syscmd( "$pod2html --title='mailadmin' bin/mailadmin > doc/mailadmin.html",
986             verbose=>0, );
987              
988 0         0 my @modules = qw/ Toaster Apache CGI Darwin DNS
989             Ezmlm FreeBSD Logs Mysql Perl
990             Qmail Setup Utility /;
991              
992             MODULE:
993 0         0 foreach my $module (@modules ) {
994 0 0       0 if ( $module =~ m/\AToaster\z/ ) {
995 0         0 $cmd = "$pod2html --title='Mail::Toaster' lib/Mail/$module.pm > doc/modules/$module.html";
996 0         0 print "$cmd\n";
997 0         0 next MODULE;
998 0         0 $self->util->syscmd( $cmd, verbose=>0 );
999             };
1000              
1001 0         0 $cmd = "$pod2html --title='Mail::Toaster::$module' lib/Mail/Toaster/$module.pm > doc/modules/$module.html";
1002 0         0 warn "$cmd\n";
1003 0         0 $self->util->syscmd( $cmd, verbose=>0 );
1004             };
1005              
1006 0         0 unlink <pod2htm*>;
1007             #$self->util->syscmd( "rm pod2html*");
1008             };
1009              
1010             sub domainkeys {
1011              
1012 0     0 0 0 my $self = shift;
1013 0         0 my %p = validate( @_, { $self->get_std_opts } );
1014              
1015 0 0       0 return $p{test_ok} if defined $p{test_ok}; # for testing only
1016              
1017 0 0       0 if ( !$self->conf->{qmail_domainkeys} ) {
1018 0         0 $self->audit( "domainkeys: installing, skipping (disabled)" );
1019 0         0 return 0;
1020             }
1021              
1022             # test to see if it is installed.
1023 0 0       0 if ( -f "/usr/local/include/domainkeys.h" ) {
1024 0         0 $self->audit( "domainkeys: installing domainkeys, ok (already installed)" );
1025 0         0 return 1;
1026             }
1027              
1028 0 0       0 if ( $OSNAME eq "freebsd" ) {
1029 0         0 $self->freebsd->install_port( "libdomainkeys" );
1030              
1031             # test to see if it installed.
1032 0 0       0 if ( -f "/usr/local/include/domainkeys.h" ) {
1033 0         0 $self->audit( "domainkeys: installing domainkeys, ok (already installed)" );
1034 0         0 return 1;
1035             }
1036             }
1037              
1038 0         0 my @targets = ( 'make', 'make setup check' );
1039              
1040 0 0       0 if ( $OSNAME eq "linux" ) {
1041 0         0 unshift @targets,
1042             'echo gcc -O2 -include /usr/include/errno.h > conf-cc';
1043             }
1044              
1045             $self->util->install_from_source(
1046 0         0 package => "libdomainkeys-0.68",
1047             site => 'http://superb-east.dl.sourceforge.net',
1048             url => '/sourceforge/domainkeys',
1049             targets => \@targets,
1050             );
1051             }
1052              
1053             sub dovecot {
1054 3     3 0 9 my $self = shift;
1055 3         7 my %p = validate( @_, { $self->get_std_opts } );
1056              
1057 3 100       18 return $p{test_ok} if defined $p{test_ok}; # for testing
1058              
1059 1 50       3 my $ver = $self->conf->{install_dovecot} or do {
1060 1         2 $self->audit( "dovecot install not selected.");
1061 1         3 return;
1062             };
1063              
1064 0 0 0     0 if ( $ver eq "port" || $ver eq "1" ) {
1065              
1066 0 0       0 if ( $self->util->find_bin( "dovecot", fatal => 0 ) ) {
1067 0         0 print "dovecot: is already installed...done.\n\n";
1068 0         0 return $self->dovecot_start();
1069             }
1070              
1071 0         0 print "dovecot: installing...\n";
1072              
1073 0 0       0 if ( $OSNAME eq "freebsd" ) {
    0          
1074 0 0       0 $self->dovecot_install_freebsd() or return;
1075 0         0 return $self->dovecot_start();
1076             }
1077             elsif ( $OSNAME eq "darwin" ) {
1078 0 0       0 return 1 if $self->darwin->install_port( "dovecot" );
1079             }
1080              
1081 0 0       0 if ( $self->util->find_bin( "dovecot", fatal => 0 ) ) {
1082 0         0 print "dovecot: install successful.\n";
1083 0         0 return $self->dovecot_start();
1084             }
1085              
1086 0         0 $ver = "1.0.7";
1087             }
1088              
1089 0         0 my $dovecot = $self->util->find_bin( "dovecot", fatal => 0 );
1090 0 0       0 if ( -x $dovecot ) {
1091 0         0 my $installed = `$dovecot --version`;
1092              
1093 0 0       0 if ( $ver eq $installed ) {
1094 0         0 print
1095             "dovecot: the selected version ($ver) is already installed!\n";
1096 0         0 $self->dovecot_start();
1097 0         0 return 1;
1098             }
1099             }
1100              
1101             $self->util->install_from_source(
1102 0         0 package => "dovecot-$ver",
1103             site => 'http://www.dovecot.org',
1104             url => '/releases',
1105             targets => [ './configure', 'make', 'make install' ],
1106             bintest => 'dovecot',
1107             verbose => 1,
1108             source_sub_dir => 'mail',
1109             );
1110              
1111 0         0 $self->dovecot_start();
1112             }
1113              
1114             sub dovecot_1_conf {
1115 0     0 0 0 my $self = shift;
1116              
1117 0         0 my $dconf = '/usr/local/etc/dovecot.conf';
1118 0 0       0 if ( ! -f $dconf ) {
1119 0         0 foreach ( qw{ /opt/local/etc /etc } ) {
1120 0         0 $dconf = "$_/dovecot.conf";
1121 0 0       0 last if -e $dconf;
1122             };
1123 0 0       0 if ( ! -f $dconf ) {
1124 0         0 return $self->error( "could not locate dovecot.conf. Toaster modifications not applied.");
1125             };
1126             };
1127              
1128 0         0 my $updated = `grep 'Mail Toaster' $dconf`;
1129 0 0       0 if ( $updated ) {
1130 0         0 $self->audit( "Toaster modifications detected, skipping config" );
1131 0         0 return 1;
1132             };
1133              
1134 0         0 my $qmaildir = $self->qmail->get_qmail_dir;
1135 0         0 $self->config->apply_tweaks(
1136             file => $dconf,
1137             changes => [
1138             { search => "protocols = imap pop3 imaps pop3s managesieve",
1139             replace => "protocols = imap pop3 imaps pop3s",
1140             nowarn => 1,
1141             },
1142             { search => "protocol pop3 {",
1143             search2 => "section",
1144             replace => "protocol pop3 {
1145             pop3_uidl_format = %08Xu%08Xv
1146             mail_plugins = quota
1147             pop3_client_workarounds = outlook-no-nuls oe-ns-eoh
1148             }",
1149             },
1150             { search => "protocol managesieve {",
1151             search2 => "section",
1152             replace => " ",
1153             nowarn => 1, # manageseive is optional build
1154             },
1155             { search => "#shutdown_clients = yes",
1156             replace => "#shutdown_clients = yes\nshutdown_clients = no",
1157             },
1158             { search => "#ssl_cert_file = /etc/ssl/certs/dovecot.pem",
1159             replace => "#ssl_cert_file = /etc/ssl/certs/dovecot.pem
1160             ssl_cert_file = $qmaildir/control/servercert.pem",
1161             },
1162             { search => "#ssl_key_file = /etc/ssl/private/dovecot.pem",
1163             replace => "#ssl_key_file = /etc/ssl/private/dovecot.pem
1164             ssl_key_file = $qmaildir/control/servercert.pem",
1165             },
1166             { search => "#login_greeting = Dovecot ready.",
1167             replace => "#login_greeting = Dovecot ready.
1168             login_greeting = Mail Toaster (Dovecot) ready.",
1169             },
1170             {
1171             search => "mail_location = mbox:~/mail/:INBOX=/var/mail/%u",
1172             replace => "#mail_location = mbox:~/mail/:INBOX=/var/mail/%u
1173             mail_location = maildir:~/Maildir",
1174             },
1175             { search => "first_valid_uid = 1000",
1176             replace => "#first_valid_uid = 1000
1177             first_valid_uid = 89",
1178             },
1179             { search => "#last_valid_uid = 0",
1180             replace => "#last_valid_uid = 0
1181             last_valid_uid = 89",
1182             },
1183             { search => "first_valid_gid = 1000",
1184             replace => "#first_valid_gid = 1000
1185             first_valid_gid = 89",
1186             },
1187             { search => "#last_valid_gid = 0",
1188             replace => "#last_valid_gid = 0\nlast_valid_gid = 89",
1189             },
1190             { search => " #mail_plugins = ",
1191             replace => " #mail_plugins = \n mail_plugins = quota imap_quota",
1192             },
1193             { search => " sendmail_path = /usr/sbin/sendmail",
1194             replace => "# sendmail_path = /usr/sbin/sendmail
1195             sendmail_path = $qmaildir/bin/sendmail",
1196             },
1197             { search => "auth_username_format = %Ln",
1198             replace => "#auth_username_format = %Ln
1199             auth_username_format = %Lu",
1200             nowarn => 1,
1201             },
1202             { search => " mechanisms = plain login",
1203             replace => " mechanisms = plain login digest-md5 cram-md5",
1204             },
1205             { search => " passdb pam {",
1206             search2 => "section",
1207             replace => " ",
1208             },
1209             { search => " #passdb vpopmail {",
1210             replace => " passdb vpopmail {\n }",
1211             },
1212             { search => " #userdb vpopmail {",
1213             replace => " userdb vpopmail {\n }",
1214             },
1215             { search => " user = root",
1216             replace => " user = vpopmail",
1217             },
1218             { search => " #quota = maildir",
1219             replace => " quota = maildir",
1220             },
1221             ],
1222             );
1223 0         0 return 1;
1224             };
1225              
1226             sub dovecot_2_conf {
1227 0     0 0 0 my $self = shift;
1228              
1229 0         0 my $dconf = '/usr/local/etc/dovecot';
1230 0 0       0 return if ! -d $dconf;
1231              
1232 0 0       0 if ( ! -f "$dconf/dovecot.conf" ) {
1233 0         0 my $ex = '/usr/local/share/doc/dovecot/example-config';
1234              
1235 0         0 foreach ( qw/ dovecot.conf / ) {
1236 0 0       0 if ( -f "$ex/$_" ) {
1237 0         0 copy("$ex/$_", $dconf);
1238             };
1239             };
1240 0         0 system "cp $ex/conf.d /usr/local/etc/dovecot";
1241             };
1242              
1243 0         0 my $updated = `grep 'Mail Toaster' $dconf/dovecot.conf`;
1244 0 0       0 if ( $updated ) {
1245 0         0 $self->audit( "Toaster modifications detected, skipping config" );
1246 0         0 return 1;
1247             };
1248              
1249 0         0 $self->config->apply_tweaks(
1250             file => "$dconf/dovecot.conf",
1251             changes => [
1252             { search => "#login_greeting = Dovecot ready.",
1253             replace => "#login_greeting = Dovecot ready.
1254             login_greeting = Mail Toaster (Dovecot) ready.",
1255             },
1256             { search => "#listen = *, ::",
1257             replace => "#listen = *, ::\nlisten = *",
1258             },
1259             ],
1260             );
1261              
1262 0         0 $self->config->apply_tweaks(
1263             file => "$dconf/conf.d/10-auth.conf",
1264             changes => [
1265             { search => "#auth_username_format =",
1266             replace => "#auth_username_format =\nauth_username_format = %Lu",
1267             nowarn => 1,
1268             },
1269             { search => "auth_mechanisms = plain",
1270             replace => "auth_mechanisms = plain login digest-md5 cram-md5",
1271             },
1272             { search => "!include auth-system.conf.ext",
1273             replace => "#!include auth-system.conf.ext",
1274             nowarn => 1,
1275             },
1276             { search => "#!include auth-vpopmail.conf.ext",
1277             replace => "!include auth-vpopmail.conf.ext",
1278             nowarn => 1,
1279             },
1280             ],
1281             );
1282              
1283 0         0 my $qmaildir = $self->qmail->get_qmail_dir;
1284 0         0 $self->config->apply_tweaks(
1285             file => "$dconf/conf.d/10-ssl.conf",
1286             changes => [
1287             { search => "ssl_cert = </etc/ssl/certs/dovecot.pem",
1288             replace => "#ssl_cert = </etc/ssl/certs/dovecot.pem
1289             ssl_cert = <$qmaildir/control/servercert.pem",
1290             },
1291             { search => "ssl_key = </etc/ssl/private/dovecot.pem",
1292             replace => "#ssl_key = </etc/ssl/private/dovecot.pem
1293             ssl_key = <$qmaildir/control/servercert.pem",
1294             },
1295             ],
1296             );
1297              
1298 0         0 $self->config->apply_tweaks(
1299             file => "$dconf/conf.d/10-mail.conf",
1300             changes => [
1301             {
1302             search => "#mail_location = ",
1303             replace => "#mail_location =
1304             mail_location = maildir:~/Maildir",
1305             },
1306             { search => "#first_valid_uid = 500",
1307             replace => "#first_valid_uid = 500\nfirst_valid_uid = 89",
1308             },
1309             { search => "#last_valid_uid = 0",
1310             replace => "#last_valid_uid = 0\nlast_valid_uid = 89",
1311             },
1312             { search => "first_valid_gid = 1",
1313             replace => "#first_valid_gid = 1\nfirst_valid_gid = 89",
1314             },
1315             { search => "#last_valid_gid = 0",
1316             replace => "#last_valid_gid = 0\nlast_valid_gid = 89",
1317             },
1318             { search => "#mail_plugins =",
1319             replace => "#mail_plugins =\nmail_plugins = quota",
1320             },
1321             ],
1322             );
1323              
1324 0         0 $self->config->apply_tweaks(
1325             file => "$dconf/conf.d/20-pop3.conf",
1326             changes => [
1327             { search => " #pop3_client_workarounds = ",
1328             replace => " #pop3_client_workarounds = \n pop3_client_workarounds = outlook-no-nuls oe-ns-eo",
1329             },
1330             ],
1331             );
1332              
1333 0         0 $self->config->apply_tweaks(
1334             file => "$dconf/conf.d/15-lda.conf",
1335             changes => [
1336             { search => "#sendmail_path = /usr/sbin/sendmail",
1337             replace => "#sendmail_path = /usr/sbin/sendmail\nsendmail_path = $qmaildir/bin/sendmail",
1338             },
1339             ],
1340             );
1341              
1342 0         0 $self->config->apply_tweaks(
1343             file => "$dconf/conf.d/90-quota.conf",
1344             changes => [
1345             { search => " #quota = maildir:User quota",
1346             replace => " quota = maildir:User quota",
1347             },
1348             ],
1349             );
1350              
1351 0         0 $self->config->apply_tweaks(
1352             file => "$dconf/conf.d/20-imap.conf",
1353             changes => [
1354             { search => " #mail_plugins = ",
1355             replace => " #mail_plugins = \n mail_plugins = \$mail_plugins imap_quota",
1356             },
1357             ],
1358             );
1359             };
1360              
1361             sub dovecot_install_freebsd {
1362 0     0 0 0 my $self = shift;
1363              
1364 0 0       0 return 1 if $self->freebsd->is_port_installed('dovecot');
1365              
1366 0         0 $self->audit( "starting port install of dovecot" );
1367              
1368 0 0       0 $self->freebsd->install_port( "dovecot",
1369             options => "# This file is generated by Mail Toaster.
1370             # Options for dovecot-1.2.17
1371             _OPTIONS_READ=dovecot-1.2.17
1372             _FILE_COMPLETE_OPTIONS_LIST=BDB GSSAPI KQUEUE LDAP MANAGESIEVE MYSQL PGSQL SQLITE SSL VPOPMAIL
1373             OPTIONS_FILE_UNSET+=BDB
1374             OPTIONS_FILE_UNSET+=GSSAPI
1375             OPTIONS_FILE_SET+=KQUEUE
1376             OPTIONS_FILE_UNSET+=LDAP
1377             OPTIONS_FILE_UNSET+=MANAGESIEVE
1378             OPTIONS_FILE_UNSET+=MYSQL
1379             OPTIONS_FILE_UNSET+=PGSQL
1380             OPTIONS_FILE_UNSET+=SQLITE
1381             OPTIONS_FILE_SET+=SSL
1382             OPTIONS_FILE_SET+=VPOPMAIL
1383             ",
1384             ) or return;
1385              
1386 0 0       0 return if ! $self->freebsd->is_port_installed('dovecot');
1387              
1388 0         0 my $config = "/usr/local/etc/dovecot.conf";
1389 0 0       0 if ( ! -e $config ) {
1390 0 0       0 if ( -e "/usr/local/etc/dovecot-example.conf" ) {
1391 0         0 copy("/usr/local/etc/dovecot-example.conf", $config);
1392             }
1393             else {
1394 0         0 $self->error("unable to find dovecot.conf sample", fatal => 0);
1395 0         0 sleep 3;
1396 0         0 return;
1397             };
1398             };
1399              
1400 0         0 return 1;
1401             }
1402              
1403             sub dovecot_start {
1404 0     0 0 0 my $self = shift;
1405              
1406 0 0       0 unless ( $OSNAME eq "freebsd" ) {
1407 0         0 $self->error( "sorry, no dovecot startup support on $OSNAME", fatal => 0);
1408 0         0 return;
1409             };
1410              
1411 0         0 $self->dovecot_1_conf();
1412 0         0 $self->dovecot_2_conf();
1413              
1414             # append dovecot_enable to /etc/rc.conf
1415 0         0 $self->freebsd->conf_check(
1416             check => "dovecot_enable",
1417             line => 'dovecot_enable="YES"',
1418             );
1419              
1420             # start dovecot
1421 0 0       0 if ( -x "/usr/local/etc/rc.d/dovecot" ) {
1422 0         0 $self->util->syscmd("/usr/local/etc/rc.d/dovecot restart", verbose=>0);
1423             };
1424             }
1425              
1426             sub enable_all_spam {
1427 0     0 0 0 my $self = shift;
1428              
1429 0         0 my $qmail_dir = $self->qmail->get_qmail_dir;
1430             my $spam_cmd = $self->conf->{qmailadmin_spam_command} ||
1431 0   0     0 '| /usr/local/bin/maildrop /usr/local/etc/mail/mailfilter';
1432              
1433 0         0 my @domains = $self->qmail->get_domains_from_assign(
1434             assign => "$qmail_dir/users/assign",
1435             );
1436              
1437 0         0 my $number_of_domains = @domains;
1438 0         0 $self->audit( "enable_all_spam: found $number_of_domains domains.");
1439              
1440 0         0 for (my $i = 0; $i < $number_of_domains; $i++) {
1441              
1442 0         0 my $domain = $domains[$i]{dom};
1443 0         0 $self->audit( "Enabling spam processing for $domain mailboxes");
1444              
1445 0         0 my @paths = `~vpopmail/bin/vuserinfo -d -D $domain`;
1446              
1447             PATH:
1448 0         0 foreach my $path (@paths) {
1449 0         0 chomp($path);
1450 0 0 0     0 if ( ! $path || ! -d $path) {
1451 0         0 $self->audit( " $path does not exist!");
1452 0         0 next PATH;
1453             };
1454              
1455 0         0 my $qpath = "$path/.qmail";
1456 0 0       0 if (-f $qpath) {
1457 0         0 $self->audit( " .qmail already exists in $path.");
1458 0         0 next PATH;
1459             };
1460              
1461 0         0 $self->audit( " .qmail created in $path.");
1462 0         0 system "echo \"$spam_cmd \" >> $path/.qmail";
1463              
1464 0         0 my $uid = getpwnam("vpopmail");
1465 0         0 my $gid = getgrnam("vchkpw");
1466 0         0 chown( $uid, $gid, "$path/.qmail" );
1467 0         0 chmod oct('0644'), "$path/.qmail";
1468             }
1469             }
1470              
1471 0         0 return 1;
1472             }
1473              
1474             sub expat {
1475 3     3 0 8 my $self = shift;
1476 3         7 my %p = validate( @_, { $self->get_std_opts } );
1477              
1478 3 100       16 return $p{test_ok} if defined $p{test_ok}; # for testing only
1479              
1480 1 50       2 if ( !$self->conf->{install_expat} ) {
1481 1         2 $self->audit( "expat: installing, skipping (disabled)" );
1482 1         3 return;
1483             }
1484              
1485 0 0       0 if ( $OSNAME eq "freebsd" ) {
    0          
1486 0 0       0 if ( -d "/usr/ports/textproc/expat" ) {
1487 0         0 return $self->freebsd->install_port( "expat" );
1488             }
1489             else {
1490 0         0 return $self->freebsd->install_port( "expat", dir => 'expat2');
1491             }
1492             }
1493             elsif ( $OSNAME eq "darwin" ) {
1494 0         0 $self->darwin->install_port( "expat" );
1495             }
1496             else {
1497 0         0 print "Sorry, build support for expat on $OSNAME is incomplete.\n";
1498             }
1499             }
1500              
1501             sub expect {
1502 0     0 1 0 my $self = shift;
1503 0         0 my %p = validate( @_, { $self->get_std_opts } );
1504              
1505 0 0       0 return $p{test_ok} if defined $p{test_ok};
1506              
1507 0 0       0 return if $OSNAME ne "freebsd";
1508              
1509             return $self->freebsd->install_port( 'expect',
1510             flags => "WITHOUT_X11=yes",
1511             fatal => $p{fatal},
1512 0         0 );
1513             }
1514              
1515             sub ezmlm {
1516 3     3 1 8 my $self = shift;
1517 3         7 my %p = validate( @_, { $self->get_std_opts } );
1518              
1519 3 100       18 return $p{test_ok} if defined $p{test_ok}; # for testing
1520              
1521 1         4 my $ver = $self->conf->{install_ezmlm};
1522 1   50     3 my $confdir = $self->conf->{system_config_dir} || "/usr/local/etc";
1523              
1524 1 50       3 if ( !$ver ) {
1525 1         2 $self->audit( "installing Ezmlm-Idx, (disabled)", verbose=>1 );
1526 1         3 return;
1527             }
1528              
1529 0         0 my $ezmlm = $self->util->find_bin( 'ezmlm-sub',
1530             dir => '/usr/local/bin/ezmlm',
1531             fatal => 0,
1532             );
1533              
1534 0 0 0     0 if ( $ezmlm && -x $ezmlm ) {
1535 0         0 $self->audit( "installing Ezmlm-Idx, ok (installed)",verbose=>1 );
1536 0         0 return $self->ezmlm_cgi();
1537             }
1538              
1539 0 0       0 $self->ezmlm_freebsd_port() and return 1;
1540 0         0 $self->ezmlm_src();
1541             };
1542              
1543             sub ezmlm_src {
1544 0     0 0 0 my $self = shift;
1545 0         0 print "ezmlm: attemping to install ezmlm from sources.\n";
1546              
1547 0         0 my $ezmlm_dist = "ezmlm-0.53";
1548 0         0 my $ver = $self->conf->{install_ezmlm};
1549 0         0 my $idx = "ezmlm-idx-$ver";
1550 0         0 my $site = "http://untroubled.org/ezmlm";
1551 0   0     0 my $src = $self->conf->{toaster_src_dir} || "/usr/local/src/mail";
1552 0   0     0 my $httpdir = $self->conf->{toaster_http_base} || "/usr/local/www";
1553 0 0       0 my $cgi = $self->toaster->get_toaster_cgibin() or die "unable to determine cgi-bin dir\n";
1554              
1555 0         0 $self->util->cwd_source_dir( "$src/mail" );
1556              
1557 0 0       0 if ( -d $ezmlm_dist ) {
1558 0 0       0 unless (
1559             $self->util->source_warning( package => $ezmlm_dist, src => "$src/mail" ) )
1560             {
1561 0         0 carp "\nezmlm: OK then, skipping install.\n";
1562 0         0 return;
1563             }
1564             else {
1565 0         0 print "ezmlm: removing any previous build sources.\n";
1566 0         0 $self->util->syscmd( "rm -rf $ezmlm_dist" );
1567             }
1568             }
1569              
1570 0 0       0 $self->util->get_url( "$site/archive/$ezmlm_dist.tar.gz" )
1571             if ! -e "$ezmlm_dist.tar.gz";
1572              
1573 0 0       0 $self->util->get_url( "$site/archive/$ver/$idx.tar.gz" )
1574             if ! -e "$idx.tar.gz";
1575              
1576 0 0       0 $self->util->extract_archive( "$ezmlm_dist.tar.gz" )
1577             or croak "Couldn't expand $ezmlm_dist.tar.gz: $!\n";
1578              
1579 0 0       0 $self->util->extract_archive( "$idx.tar.gz" )
1580             or croak "Couldn't expand $idx.tar.gz: $!\n";
1581              
1582 0         0 $self->util->syscmd( "mv $idx/* $ezmlm_dist/", );
1583 0         0 $self->util->syscmd( "rm -rf $idx", );
1584              
1585 0         0 chdir($ezmlm_dist);
1586              
1587 0         0 $self->util->syscmd( "patch < idx.patch", );
1588 0         0 $self->ezmlm_conf_fixups();
1589              
1590 0         0 $self->util->syscmd( "make" );
1591 0         0 $self->util->syscmd( "chmod 775 makelang" );
1592              
1593             #$self->util->syscmd( "make mysql" ); # haven't figured this out yet (compile problems)
1594 0         0 $self->util->syscmd( "make man" );
1595 0         0 $self->util->syscmd( "make setup");
1596              
1597 0         0 $self->ezmlm_cgi();
1598 0         0 return 1;
1599             }
1600              
1601             sub ezmlm_conf_fixups {
1602 0     0 0 0 my $self = shift;
1603              
1604 0 0       0 if ( $OSNAME eq "darwin" ) {
    0          
1605 0         0 my $local_include = "/usr/local/mysql/include";
1606 0         0 my $local_lib = "/usr/local/mysql/lib";
1607              
1608 0 0       0 if ( !-d $local_include ) {
1609 0         0 $local_include = "/opt/local/include/mysql";
1610 0         0 $local_lib = "/opt/local/lib/mysql";
1611             }
1612              
1613 0         0 $self->util->file_write( "sub_mysql/conf-sqlcc",
1614             lines => ["-I$local_include"],
1615             );
1616              
1617 0         0 $self->util->file_write( "sub_mysql/conf-sqlld",
1618             lines => ["-L$local_lib -lmysqlclient -lm"],
1619             );
1620             }
1621             elsif ( $OSNAME eq "freebsd" ) {
1622 0         0 $self->util->file_write( "sub_mysql/conf-sqlcc",
1623             lines => ["-I/usr/local/include/mysql"],
1624             );
1625              
1626 0         0 $self->util->file_write( "sub_mysql/conf-sqlld",
1627             lines => ["-L/usr/local/lib/mysql -lmysqlclient -lnsl -lm"],
1628             );
1629             }
1630              
1631 0         0 $self->util->file_write( "conf-bin", lines => ["/usr/local/bin"] );
1632 0         0 $self->util->file_write( "conf-man", lines => ["/usr/local/man"] );
1633 0         0 $self->util->file_write( "conf-etc", lines => ["/usr/local/etc"] );
1634             };
1635              
1636             sub ezmlm_cgi {
1637 0     0 0 0 my $self = shift;
1638 0         0 my %p = validate( @_, { $self->get_std_opts } );
1639              
1640 0 0       0 return $p{test_ok} if defined $p{test_ok}; # for testing
1641              
1642 0 0       0 return 1 if ! $self->conf->{install_ezmlm_cgi};
1643              
1644 0 0       0 if ( $OSNAME eq "freebsd" ) {
1645 0         0 $self->freebsd->install_port( "p5-Archive-Tar",
1646             options=>"#
1647             # This file was generated by Mail::Toaster
1648             # No user-servicable parts inside!
1649             # Options for p5-Archive-Tar-1.30
1650             _OPTIONS_READ=p5-Archive-Tar-1.30
1651             WITHOUT_TEXT_DIFF=true",
1652             );
1653             }
1654              
1655 0         0 $self->util->install_module( "Email::Valid" );
1656 0         0 $self->util->install_module( "Mail::Ezmlm" );
1657              
1658 0         0 return 1;
1659             }
1660              
1661             sub ezmlm_freebsd_port {
1662 0     0 0 0 my $self = shift;
1663              
1664 0 0       0 return if $OSNAME ne "freebsd";
1665 0 0       0 return if $self->conf->{install_ezmlm} ne "port";
1666 0 0       0 return 1 if $self->freebsd->is_port_installed( "ezmlm", fatal=>0 );
1667              
1668 0         0 my $defs = '';
1669 0 0       0 my $myopt = $self->conf->{install_ezmlm_mysql} ? 'SET' : 'UNSET';
1670              
1671 0 0       0 $self->freebsd->install_port( "ezmlm-idx",
1672             options => "# This file was generated by mail-toaster
1673             # Options for ezmlm-idx-7.1.1_1
1674             _OPTIONS_READ=ezmlm-idx-7.1.1_1
1675             _FILE_COMPLETE_OPTIONS_LIST=DB DOCS MYSQL PGSQL SQLITE
1676             OPTIONS_FILE_$myopt+=DB
1677             OPTIONS_FILE_SET+=DOCS
1678             OPTIONS_FILE_$myopt+=MYSQL
1679             OPTIONS_FILE_UNSET+=PGSQL
1680             OPTIONS_FILE_UNSET+=SQLITE
1681             ",
1682             )
1683             or return $self->error( "ezmlm-idx install failed" );
1684              
1685 0   0     0 my $confdir = $self->conf->{system_config_dir} || "/usr/local/etc";
1686 0         0 chdir("$confdir/ezmlm");
1687 0 0       0 copy( "ezmlmglrc.sample", "ezmlmglrc" )
1688             or $self->util->error( "copy ezmlmglrc failed: $!");
1689              
1690 0 0       0 copy( "ezmlmrc.sample", "ezmlmrc" )
1691             or $self->util->error( "copy ezmlmrc failed: $!");
1692              
1693 0 0       0 copy( "ezmlmsubrc.sample", "ezmlmsubrc" )
1694             or $self->util->error( "copy ezmlmsubrc failed: $!");
1695              
1696 0         0 return $self->ezmlm_cgi();
1697             };
1698              
1699             sub filtering {
1700 2     2 1 3 my $self = shift;
1701 2         6 my %p = validate( @_, { $self->get_std_opts },);
1702              
1703 2 50       17 return $p{test_ok} if defined $p{test_ok}; # for testing
1704              
1705 0 0       0 if ( $OSNAME eq "freebsd" ) {
1706              
1707 0         0 $self->maildrop->install;
1708              
1709 0         0 $self->freebsd->install_port( "p5-Archive-Tar",
1710             options=> "# This file was generated by mail-toaster
1711             # No user-servicable parts inside!
1712             # Options for p5-Archive-Tar-1.30
1713             _OPTIONS_READ=p5-Archive-Tar-1.30
1714             WITHOUT_TEXT_DIFF=true",
1715             );
1716              
1717 0         0 $self->freebsd->install_port( "p5-Mail-Audit" );
1718 0         0 $self->freebsd->install_port( "unzip" );
1719              
1720 0         0 $self->razor();
1721              
1722 0 0       0 $self->freebsd->install_port( "pyzor" ) if $self->conf->{install_pyzor};
1723 0 0       0 $self->freebsd->install_port( "bogofilter" ) if $self->conf->{install_bogofilter};
1724             $self->freebsd->install_port( "dcc-dccd",
1725             flags => "WITHOUT_SENDMAIL=yes",
1726             options => "# This file generated by mail-toaster
1727             # Options for dcc-dccd-1.3.116
1728             _OPTIONS_READ=dcc-dccd-1.3.116
1729             WITH_DCCIFD=true
1730             WITHOUT_DCCM=true
1731             WITH_DCCD=true
1732             WITH_DCCGREY=true
1733             WITH_IPV6=true
1734             WITHOUT_ALT_HOME=true
1735             WITHOUT_PORTS_SENDMAIL=true\n",
1736 0 0       0 ) if $self->conf->{install_dcc};
1737              
1738 0 0       0 $self->freebsd->install_port( "procmail" ) if $self->conf->{install_procmail};
1739 0         0 $self->freebsd->install_port( "p5-Email-Valid" );
1740             }
1741              
1742 0         0 $self->spamassassin;
1743 0         0 $self->razor;
1744 0         0 $self->clamav;
1745 0         0 $self->simscan->install;
1746             }
1747              
1748             sub gmake_freebsd {
1749 0     0 0 0 my $self = shift;
1750              
1751             # iconv to suppress a prompt, and because gettext requires it
1752 0 0       0 if (!$self->freebsd->is_port_installed('libiconv')) {
1753 0         0 $self->freebsd->install_package('libiconv');
1754 0 0       0 if (!$self->freebsd->is_port_installed('libiconv')) {
1755 0         0 $self->freebsd->install_port( 'libiconv',
1756             options => "#\n# This file was generated by mail-toaster
1757             # Options for libiconv-1.13.1_1
1758             _OPTIONS_READ=libiconv-1.13.1_1
1759             WITH_EXTRA_ENCODINGS=true
1760             WITHOUT_EXTRA_PATCHES=true\n",
1761             );
1762             }
1763             }
1764              
1765             # required by gmake
1766 0 0       0 if (!$self->freebsd->is_port_installed('gettext')) {
1767 0         0 $self->freebsd->install_package('gettext');
1768 0 0       0 if (!$self->freebsd->is_port_installed('gettext')) {
1769 0         0 $self->freebsd->install_port( "gettext",
1770             options => "#\n# This file was generated by mail-toaster
1771             # Options for gettext-0.14.5_2
1772             _OPTIONS_READ=gettext-0.14.5_2\n",
1773             );
1774             }
1775             }
1776              
1777 0 0       0 if (!$self->freebsd->is_port_installed('gmake')) {
1778 0         0 $self->freebsd->install_package('gmake');
1779 0 0       0 if (!$self->freebsd->is_port_installed('gmake')) {
1780 0         0 $self->freebsd->install_port( 'gmake' );
1781             }
1782             }
1783             };
1784              
1785             sub gnupg_install {
1786 0     0 0 0 my $self = shift;
1787 0 0       0 return if ! $self->conf->{install_gnupg};
1788              
1789 0 0       0 if ( $self->conf->{package_install_method} eq 'packages' ) {
1790 0         0 $self->freebsd->install_package( "gnupg", verbose=>0, fatal => 0 );
1791 0 0       0 return 1 if $self->freebsd->is_port_installed('gnupg');
1792             };
1793              
1794 0         0 $self->freebsd->install_port( "gnupg",
1795             verbose => 0,
1796             options => "# This file was generated by mail-toaster
1797             # No user-servicable parts inside!
1798             # Options for gnupg-1.4.5
1799             _OPTIONS_READ=gnupg-1.4.5
1800             WITHOUT_LDAP=true
1801             WITHOUT_LIBICONV=true
1802             WITHOUT_LIBUSB=true
1803             WITHOUT_SUID_GPG=true
1804             WITH_NLS=true",
1805             );
1806             };
1807              
1808             sub group_add {
1809 0     0 0 0 my $self = shift;
1810 0         0 my ($group, $gid) = @_;
1811 0 0       0 return if ! $group;
1812 0 0       0 return if $self->group_exists($group);
1813 0         0 my $cmd;
1814 0 0       0 if ( $OSNAME eq 'linux' ) {
    0          
    0          
1815 0         0 $cmd = $self->util->find_bin('groupadd');
1816 0 0       0 $cmd .= " -g $gid" if $gid;
1817 0         0 $cmd .= " $group";
1818             }
1819             elsif ( $OSNAME eq 'freebsd' ) {
1820 0         0 $cmd = $self->util->find_bin( 'pw' );
1821 0         0 $cmd .= " groupadd -n $group";
1822 0 0       0 $cmd .= " -g $gid" if $gid;
1823             }
1824             elsif ( $OSNAME eq 'darwin' ) {
1825 0         0 $cmd = $self->util->find_bin( "dscl", fatal => 0 );
1826 0         0 my $path = "/groups/$group";
1827 0 0       0 if ($cmd) { # use dscl 10.5+
1828 0         0 $self->util->syscmd( "$cmd . -create $path" );
1829 0 0       0 $self->util->syscmd( "$cmd . -createprop $path gid $gid") if $gid;
1830 0         0 $self->util->syscmd( "$cmd . -createprop $path passwd '*'" );
1831             }
1832             else {
1833 0         0 $cmd = $self->util->find_bin( "niutil", fatal => 0 );
1834 0         0 $self->util->syscmd( "$cmd -create . $path" );
1835 0 0       0 $self->util->syscmd( "$cmd -createprop . $path gid $gid") if $gid;
1836 0         0 $self->util->syscmd( "$cmd -createprop . $path passwd '*'" );
1837             }
1838 0         0 return 1;
1839             }
1840             else {
1841 0         0 warn "unable to create users on OS $OSNAME\n";
1842 0         0 return;
1843             };
1844 0         0 return $self->util->syscmd( $cmd );
1845             };
1846              
1847             sub group_exists {
1848 0     0 0 0 my $self = shift;
1849 0 0       0 my $group = lc(shift) or die "missing group";
1850 0         0 my $gid = getgrnam($group);
1851 0 0 0     0 return ( $gid && $gid > 0 ) ? $gid : undef;
1852             };
1853              
1854             sub has_module {
1855 0     0 0 0 my $self = shift;
1856 0         0 my ($name, $ver) = @_;
1857              
1858             ## no critic ( ProhibitStringyEval )
1859 0 0       0 eval "use $name" . ($ver ? " $ver;" : ";");
1860             ## use critic
1861              
1862 0         0 !$EVAL_ERROR;
1863             };
1864              
1865             sub is_newer {
1866 6     6 0 8 my $self = shift;
1867 6         15 my %p = validate( @_, { 'min' => SCALAR, 'cur' => SCALAR, $self->get_std_opts } );
1868              
1869 6         23 my ( $min, $cur ) = ( $p{min}, $p{cur} );
1870              
1871 6         12 my @mins = split( q{\.}, $min );
1872 6         9 my @curs = split( q{\.}, $cur );
1873              
1874             #use Data::Dumper;
1875             #print Dumper(@mins, @curs);
1876              
1877 6 100       15 if ( $curs[0] > $mins[0] ) { return 1; } # major version num
  1         4  
1878 5 100       8 if ( $curs[1] > $mins[1] ) { return 1; } # minor version num
  1         6  
1879 4 100 33     22 if ( $curs[2] && $mins[2] && $curs[2] > $mins[2] ) { return 1; } # revision level
  1   66     6  
1880 3 0 33     7 if ( $curs[3] && $mins[3] && $curs[3] > $mins[3] ) { return 1; } # just in case
  0   0     0  
1881              
1882 3         10 return 0;
1883             }
1884              
1885             sub isoqlog {
1886 0     0 0 0 my $self = shift;
1887 0         0 my %p = validate( @_, { $self->get_std_opts },);
1888              
1889             my $ver = $self->conf->{install_isoqlog}
1890 0 0       0 or return $self->audit( "install_isoqlog is disabled",verbose=>1 );
1891              
1892 0         0 my $return = 0;
1893              
1894 0 0       0 if ( $ver eq "port" ) {
1895 0 0       0 if ( $OSNAME eq "freebsd" ) {
1896 0         0 $self->freebsd->install_port( "isoqlog" );
1897 0         0 $self->isoqlog_conf();
1898 0 0       0 return 1 if $self->freebsd->is_port_installed( "isoqlog", %p );
1899             }
1900             else {
1901 0         0 return $self->error(
1902             "isoqlog: install_isoqlog = port is not valid for $OSNAME" );
1903             }
1904             }
1905             else {
1906 0 0       0 if ( $self->util->find_bin( "isoqlog", fatal => 0 ) ) {
1907 0         0 $self->isoqlog_conf();
1908 0         0 $self->audit( "isoqlog: install, ok (exists)" );
1909 0         0 return 2;
1910             }
1911             }
1912              
1913 0 0       0 return $return if $self->util->find_bin( "isoqlog", fatal => 0 );
1914              
1915 0         0 $self->audit( "isoqlog not found. Attempting source install ($ver) on $OSNAME!");
1916              
1917 0 0 0     0 $ver = 2.2 if ( $ver eq "port" || $ver == 1 );
1918              
1919 0         0 my $configure = "./configure ";
1920              
1921 0 0       0 if ( $self->conf->{toaster_prefix} ) {
1922 0         0 $configure .= "--prefix=" . $self->conf->{toaster_prefix} . " ";
1923 0         0 $configure .= "--exec-prefix=" . $self->conf->{toaster_prefix} . " ";
1924             }
1925              
1926 0 0       0 if ( $self->conf->{system_config_dir} ) {
1927 0         0 $configure .= "--sysconfdir=" . $self->conf->{system_config_dir} . " ";
1928             }
1929              
1930 0         0 $self->audit( "isoqlog: building with $configure" );
1931              
1932 0         0 $self->util->install_from_source(
1933             package => "isoqlog-$ver",
1934             site => 'http://www.enderunix.org',
1935             url => '/isoqlog',
1936             targets => [ $configure, 'make', 'make install', 'make clean' ],
1937             bintest => 'isoqlog',
1938             source_sub_dir => 'mail',
1939             %p
1940             );
1941              
1942 0 0       0 if ( $self->conf->{toaster_prefix} ne "/usr/local" ) {
1943             symlink( "/usr/local/share/isoqlog",
1944 0         0 $self->conf->{toaster_prefix} . "/share/isoqlog" );
1945             }
1946              
1947 0 0       0 if ( $self->util->find_bin( "isoqlog", fatal => 0 ) ) {
1948 0         0 return $self->isoqlog_conf();
1949             };
1950              
1951 0         0 return;
1952             }
1953              
1954             sub isoqlog_conf {
1955 0     0 0 0 my $self = shift;
1956 0         0 my %p = validate( @_, { $self->get_std_opts },);
1957              
1958             # isoqlog doesn't honor --sysconfdir yet
1959             #my $etc = $self->conf->{system_config_dir} || "/usr/local/etc";
1960 0         0 my $etc = "/usr/local/etc";
1961 0         0 my $file = "$etc/isoqlog.conf";
1962              
1963 0 0       0 if ( -e $file ) {
1964 0         0 $self->audit( "isoqlog_conf: creating $file, ok (exists)" );
1965 0         0 return 2;
1966             }
1967              
1968 0         0 my @lines;
1969              
1970 0   0     0 my $htdocs = $self->conf->{toaster_http_docs} || "/usr/local/www/data";
1971 0   0     0 my $hostn = $self->conf->{toaster_hostname} || hostname;
1972 0   0     0 my $logdir = $self->conf->{qmail_log_base} || "/var/log/mail";
1973 0         0 my $qmaild = $self->qmail->get_qmail_dir;
1974 0   0     0 my $prefix = $self->conf->{toaster_prefix} || "/usr/local";
1975              
1976 0         0 push @lines, <<EO_ISOQLOG;
1977             #isoqlog Configuration file
1978              
1979             logtype = "qmail-multilog"
1980             logstore = "$logdir/send"
1981             domainsfile = "$qmaild/control/rcpthosts"
1982             outputdir = "$htdocs/isoqlog"
1983             htmldir = "$prefix/share/isoqlog/htmltemp"
1984             langfile = "$prefix/share/isoqlog/lang/english"
1985             hostname = "$hostn"
1986              
1987             maxsender = 100
1988             maxreceiver = 100
1989             maxtotal = 100
1990             maxbyte = 100
1991             EO_ISOQLOG
1992              
1993 0 0       0 $self->util->file_write( $file, lines => \@lines )
1994             or $self->error( "couldn't write $file: $!");
1995 0         0 $self->audit( "isoqlog_conf: created $file, ok" );
1996              
1997 0         0 $self->util->syscmd( "isoqlog", fatal => 0 );
1998              
1999             # if missing, create the isoqlog web directory
2000 0 0       0 if ( ! -e "$htdocs/isoqlog" ) {
2001 0         0 mkdir oct('0755'), "$htdocs/isoqlog";
2002             };
2003              
2004             # to fix the missing images problem, add a web server alias like:
2005             # Alias /isoqlog/images/ "/usr/local/share/isoqlog/htmltemp/images/"
2006             }
2007              
2008             sub lighttpd {
2009 3     3 0 10 my $self = shift;
2010 3         7 my %p = validate( @_, { $self->get_std_opts } );
2011 3 100       16 return $p{test_ok} if defined $p{test_ok}; # for testing
2012              
2013 1 50       4 if ( ! $self->conf->{install_lighttpd} ) {
2014 1         2 $self->audit("skipping lighttpd install (disabled)");
2015 1         3 return;
2016             };
2017              
2018 0 0       0 if ( $OSNAME eq 'freebsd' ) {
2019 0         0 $self->lighttpd_freebsd();
2020             }
2021             else {
2022 0 0       0 $self->util->find_bin( 'lighttpd', fatal=>0)
2023             or return $self->error("no support for install lighttpd on $OSNAME. Report this error to support\@tnpi.net");
2024             };
2025              
2026 0         0 $self->lighttpd_config();
2027 0         0 $self->lighttpd_vhost();
2028 0         0 $self->php();
2029 0         0 $self->lighttpd_start();
2030 0         0 return 1;
2031             };
2032              
2033             sub lighttpd_freebsd {
2034 0     0 0 0 my $self = shift;
2035              
2036             # installing manually overrides the dialogs
2037 0         0 $self->freebsd->install_port( 'm4',
2038             options => "# this file installed by mail-toaster
2039             # Options for m4-1.4.16_1,1
2040             _OPTIONS_READ=m4-1.4.16_1,1
2041             _FILE_COMPLETE_OPTIONS_LIST=LIBSIGSEGV
2042             OPTIONS_FILE_UNSET+=LIBSIGSEGV
2043             ",
2044             );
2045 0         0 $self->freebsd->install_port( 'help2man',
2046             options => "# this file installed by mail-toaster
2047             # Options for help2man-1.43.2
2048             _OPTIONS_READ=help2man-1.43.2
2049             _FILE_COMPLETE_OPTIONS_LIST=NLS
2050             OPTIONS_FILE_UNSET+=NLS
2051             ",
2052             );
2053 0         0 $self->freebsd->install_port( 'lighttpd',
2054             options => "#\n# This file was generated by mail-toaster
2055             # Options for lighttpd-1.4.32_1
2056             _OPTIONS_READ=lighttpd-1.4.32_1
2057             _FILE_COMPLETE_OPTIONS_LIST=BZIP2 FAM GDBM IPV6 LDAP LIBEV LUA MEMCACHE MYSQL MYSQLAUTH NODELAY OPENSSL REMOTEUSER SPAWNFCGI VALGRIND WEBDAV
2058             OPTIONS_FILE_SET+=BZIP2
2059             OPTIONS_FILE_UNSET+=FAM
2060             OPTIONS_FILE_UNSET+=GDBM
2061             OPTIONS_FILE_UNSET+=IPV6
2062             OPTIONS_FILE_UNSET+=LDAP
2063             OPTIONS_FILE_UNSET+=LIBEV
2064             OPTIONS_FILE_UNSET+=LUA
2065             OPTIONS_FILE_UNSET+=MEMCACHE
2066             OPTIONS_FILE_UNSET+=MYSQL
2067             OPTIONS_FILE_UNSET+=MYSQLAUTH
2068             OPTIONS_FILE_UNSET+=NODELAY
2069             OPTIONS_FILE_SET+=OPENSSL
2070             OPTIONS_FILE_UNSET+=REMOTEUSER
2071             OPTIONS_FILE_SET+=SPAWNFCGI
2072             OPTIONS_FILE_UNSET+=VALGRIND
2073             OPTIONS_FILE_UNSET+=WEBDAV
2074             ",
2075             );
2076              
2077 0         0 $self->freebsd->conf_check(
2078             check => "lighttpd_enable",
2079             line => 'lighttpd_enable="YES"',
2080             );
2081              
2082 0         0 my @logs = qw/ lighttpd.error.log lighttpd.access.log /;
2083 0         0 foreach ( @logs ) {
2084 0 0       0 $self->util->file_write( "/var/log/$_", lines => [' '] )
2085             if ! -e "/var/log/$_";
2086 0         0 $self->util->chown("/var/log/$_", uid => 'www', gid => 'www');
2087             };
2088             };
2089              
2090             sub lighttpd_config {
2091 0     0 0 0 my $self = shift;
2092              
2093 0         0 my $letc = '/usr/local/etc';
2094 0 0       0 $letc = "$letc/lighttpd" if -d "$letc/lighttpd";
2095              
2096 0         0 my $lconf = "$letc/lighttpd.conf";
2097              
2098 0 0       0 `grep toaster $letc/lighttpd.conf`
2099             and return $self->audit("lighttpd configuration already done");
2100              
2101 0   0     0 my $cgi_bin = $self->conf->{toaster_cgi_bin} || '/usr/local/www/cgi-bin.toaster/';
2102 0   0     0 my $htdocs = $self->conf->{toaster_http_docs} || '/usr/local/www/toaster';
2103              
2104 0         0 $self->config->apply_tweaks(
2105             file => "$letc/lighttpd.conf",
2106             changes => [
2107             { search => q{# "mod_redirect",},
2108             replace => q{ "mod_redirect",},
2109             },
2110             { search => q{# "mod_alias",},
2111             replace => q{ "mod_alias",},
2112             },
2113             { search => q{# "mod_auth",},
2114             replace => q{ "mod_auth",},
2115             },
2116             { search => q{# "mod_setenv",},
2117             replace => q{ "mod_setenv",},
2118             },
2119             { search => q{# "mod_fastcgi",},
2120             replace => q{ "mod_fastcgi",},
2121             },
2122             { search => q{# "mod_cgi",},
2123             replace => q{ "mod_cgi",},
2124             },
2125             { search => q{# "mod_compress",},
2126             replace => q{ "mod_compress",},
2127             },
2128             { search => q{server.document-root = "/usr/local/www/data/"},
2129             replace => qq{server.document-root = "$htdocs/"},
2130             },
2131             { search => q{server.document-root = "/usr/local/www/data/"},
2132             replace => qq{server.document-root = "$htdocs/"},
2133             },
2134             { search => q{var.server_root = "/usr/local/www/data"},
2135             replace => qq{var.server_root = "$htdocs"},
2136             },
2137             { search => q{#include_shell "cat /usr/local/etc/lighttpd/vhosts.d/*.conf"},
2138             replace => q{include_shell "cat /usr/local/etc/lighttpd/vhosts.d/*.conf"},
2139             },
2140             { search => q'$SERVER["socket"] == "0.0.0.0:80" { }',
2141             replace => q'#$SERVER["socket"] == "0.0.0.0:80" { }',
2142             },
2143             ],
2144             );
2145              
2146 0         0 $self->config->apply_tweaks(
2147             file => "$letc/modules.conf",
2148             changes => [
2149             { search => q{# "mod_alias",},
2150             replace => q{ "mod_alias",},
2151             },
2152             { search => q{# "mod_auth",},
2153             replace => q{ "mod_auth",},
2154             },
2155             { search => q{# "mod_redirect",},
2156             replace => q{ "mod_redirect",},
2157             },
2158             { search => q{# "mod_setenv",},
2159             replace => q{ "mod_setenv",},
2160             },
2161             { search => q{#include "conf.d/cgi.conf"},
2162             replace => q{include "conf.d/cgi.conf"},
2163             },
2164             { search => q{#include "conf.d/fastcgi.conf"},
2165             replace => q{include "conf.d/fastcgi.conf"},
2166             },
2167             ],
2168             );
2169              
2170 0         0 return 1;
2171             };
2172              
2173             sub lighttpd_start {
2174 0     0 0 0 my $self = shift;
2175              
2176 0 0       0 if ( $OSNAME eq 'freebsd' ) {
    0          
2177 0         0 system "/usr/local/etc/rc.d/lighttpd restart";
2178 0         0 return 1;
2179             }
2180             elsif ( $OSNAME eq 'linux' ) {
2181 0         0 system "service lighttpd start";
2182 0         0 return 1;
2183             };
2184 0         0 print "not sure how to start lighttpd on $OSNAME\n";
2185 0         0 return;
2186             };
2187              
2188             sub lighttpd_vhost {
2189 0     0 0 0 my $self = shift;
2190              
2191 0         0 my $letc = '/usr/local/etc';
2192 0 0       0 $letc = "$letc/lighttpd" if -d "$letc/lighttpd";
2193              
2194 0         0 my $www = '/usr/local/www';
2195 0   0     0 my $cgi_bin = $self->conf->{toaster_cgi_bin} || "$www/cgi-bin.toaster/";
2196 0   0     0 my $htdocs = $self->conf->{toaster_http_docs} || "$www/toaster";
2197              
2198 0         0 my $vhost = '
2199             alias.url = (
2200             "/sqwebmail/" => "' . $htdocs . '/sqwebmail/",
2201             "/qmailadmin/" => "/usr/local/www/data.default/qmailadmin/",
2202             "/cgi-bin/qmailadmin/" => "/usr/local/www/cgi-bin.default/qmailadmin/"
2203             "/cgi-bin/" => "' . $cgi_bin . '/",
2204             "/squirrelmail/" => "' . $www . '/squirrelmail/",
2205             "/roundcube/" => "' . $www . '/roundcube/",
2206             "/v-webmail/" => "' . $www . '/v-webmail/htdocs/",
2207             "/horde/" => "' . $www . '/horde/",
2208             "/awstatsclasses" => "' . $www . '/awstats/classes/",
2209             "/awstatscss" => "' . $www . '/awstats/css/",
2210             "/awstatsicons" => "' . $www . '/awstats/icons/",
2211             "/awstats/" => "' . $www . '/awstats/cgi-bin/",
2212             "/munin/" => "' . $www . '/munin/",
2213             "/rrdutil/" => "/usr/local/rrdutil/html/",
2214             "/isoqlog/images/"=> "/usr/local/share/isoqlog/htmltemp/images/",
2215             "/phpMyAdmin/" => "' . $www . '/phpMyAdmin/",
2216             )
2217              
2218             $HTTP["url"] =~ "^/awstats/" {
2219             cgi.assign = ( "" => "/usr/bin/perl" )
2220             }
2221             $HTTP["url"] =~ "^/cgi-bin" {
2222             cgi.assign = ( "" => "" )
2223             }
2224             $HTTP["url"] =~ "^/ezmlm.cgi" {
2225             cgi.assign = ( "" => "/usr/bin/perl" )
2226             }
2227              
2228             # redirect users to a secure connection
2229             $SERVER["socket"] == ":80" {
2230             $HTTP["host"] =~ "(.*)" {
2231             url.redirect = ( "^/(.*)" => "https://%1/$1" )
2232             }
2233             }
2234              
2235             $SERVER["socket"] == ":443" {
2236             ssl.engine = "enable"
2237             ssl.pemfile = "/usr/local/openssl/certs/server.pem"
2238             # sqwebmail needs this
2239             setenv.add-environment = ( "HTTPS" => "on" )
2240             }
2241              
2242             fastcgi.server = (
2243             ".php" =>
2244             ( "localhost" =>
2245             (
2246             "socket" => "/tmp/php-fastcgi.socket",
2247             "bin-path" => "/usr/local/bin/php-cgi",
2248             "idle-timeout" => 1200,
2249             "min-procs" => 1,
2250             "max-procs" => 3,
2251             "bin-environment" => (
2252             "PHP_FCGI_CHILDREN" => "2",
2253             "PHP_FCGI_MAX_REQUESTS" => "100"
2254             ),
2255             )
2256             )
2257             )
2258              
2259             auth.backend = "htdigest"
2260             auth.backend.htdigest.userfile = "/usr/local/etc/WebUsers"
2261              
2262             auth.require = ( "/isoqlog" =>
2263             (
2264             "method" => "digest",
2265             "realm" => "Admins Only",
2266             "require" => "valid-user"
2267             ),
2268             "/cgi-bin/vqadmin" =>
2269             (
2270             "method" => "digest",
2271             "realm" => "Admins Only",
2272             "require" => "valid-user"
2273             ),
2274             "/ezmlm.cgi" =>
2275             (
2276             "method" => "digest",
2277             "realm" => "Admins Only",
2278             "require" => "valid-user"
2279             )
2280             # "/munin" =>
2281             # (
2282             # "method" => "digest",
2283             # "realm" => "Admins Only",
2284             # "require" => "valid-user"
2285             # )
2286             )
2287             ';
2288              
2289 0         0 $self->util->file_write("$letc/vhosts.d/mail-toaster.conf", lines => [ $vhost ],);
2290 0         0 return 1;
2291             };
2292              
2293             sub logmonster {
2294 0     0 0 0 my $self = shift;
2295 0         0 my $verbose = $self->verbose;
2296              
2297 0         0 my %p = validate( @_, {
2298             fatal => { type => BOOLEAN, optional => 1, default => 1 },
2299             verbose => { type => BOOLEAN, optional => 1, default => $verbose },
2300             test_ok => { type => BOOLEAN, optional => 1, },
2301             },
2302             );
2303              
2304 0         0 my $fatal = $p{fatal};
2305 0         0 $verbose = $p{verbose};
2306              
2307 0         0 my $perlbin = $self->util->find_bin( "perl", verbose => $verbose );
2308              
2309 0         0 my @targets = ( "$perlbin Makefile.PL", "make", "make install" );
2310 0 0       0 push @targets, "make test" if $verbose;
2311              
2312 0         0 $self->util->install_module_from_src( 'Apache-Logmonster',
2313             site => 'http://www.tnpi.net',
2314             archive => 'Apache-Logmonster',
2315             url => '/internet/www/logmonster',
2316             targets => \@targets,
2317             verbose => $verbose,
2318             );
2319             }
2320              
2321             sub maildrop {
2322 0     0 0 0 require Mail::Toaster::Setup::Maildrop;
2323 0         0 return Mail::Toaster::Setup::Maildrop->new;
2324             };
2325              
2326             sub maillogs {
2327 0     0 1 0 my $self = shift;
2328 0         0 my %p = validate( @_, { $self->get_std_opts } );
2329 0         0 my %args = $self->get_std_args( %p );
2330              
2331 0 0       0 return $p{test_ok} if defined $p{test_ok}; # for testing
2332              
2333 0   0     0 my $user = $self->conf->{qmail_log_user} || "qmaill";
2334 0   0     0 my $group = $self->conf->{qmail_log_group} || "qnofiles";
2335 0   0     0 my $logdir = $self->conf->{qmail_log_base} || "/var/log/mail";
2336              
2337 0         0 my $uid = getpwnam($user);
2338 0         0 my $gid = getgrnam($group);
2339              
2340 0 0 0     0 return $self->error( "The user $user or group $group does not exist." )
2341             unless ( defined $uid && defined $gid );
2342              
2343 0         0 $self->toaster->supervise_dirs_create( verbose=>1 );
2344              
2345 0         0 $self->maillogs_create_dirs();
2346              
2347 0         0 $self->cronolog();
2348 0         0 $self->isoqlog();
2349              
2350 0         0 $self->logs->verify_settings();
2351             }
2352              
2353             sub maillogs_create_dirs {
2354 0     0 0 0 my $self = shift;
2355              
2356 0   0     0 my $user = $self->conf->{qmail_log_user} || "qmaill";
2357 0   0     0 my $group = $self->conf->{qmail_log_group} || "qnofiles";
2358 0         0 my $uid = getpwnam($user);
2359 0         0 my $gid = getgrnam($group);
2360              
2361             # if it exists, make sure it's owned by qmail:qnofiles
2362 0   0     0 my $logdir = $self->conf->{qmail_log_base} || "/var/log/mail";
2363 0 0       0 if ( -w $logdir ) {
2364 0 0       0 chown( $uid, $gid, $logdir )
2365             or $self->error( "Couldn't chown $logdir to $uid: $!");
2366 0         0 $self->audit( "maillogs: set ownership of $logdir to $user",verbose=>1 );
2367             }
2368              
2369 0 0       0 if ( ! -d $logdir ) {
2370 0 0       0 mkdir( $logdir, oct('0755') )
2371             or $self->error( "maillogs: couldn't create $logdir: $!" );
2372 0 0       0 chown( $uid, $gid, $logdir )
2373             or $self->error( "maillogs: couldn't chown $logdir: $!");
2374 0         0 $self->audit( "maillogs: created $logdir", verbose=>1 );
2375             }
2376              
2377 0         0 foreach my $prot (qw/ send smtp pop3 submit /) {
2378 0         0 my $dir = "$logdir/$prot";
2379 0 0       0 if ( -d $dir ) {
2380 0         0 $self->audit( "maillogs: create $dir, (exists)", verbose=>1 );
2381             }
2382             else {
2383 0 0       0 mkdir( $dir, oct('0755') )
2384             or $self->error( "maillogs: couldn't create $dir: $!" );
2385 0         0 $self->audit( "maillogs: created $dir", verbose=>1);
2386             }
2387 0 0       0 chown( $uid, $gid, $dir )
2388             or $self->error( "maillogs: chown $dir failed: $!");
2389             }
2390             };
2391              
2392             sub mrm {
2393 0     0 0 0 my $self = shift;
2394 0         0 my $verbose = $self->{verbose};
2395              
2396 0         0 my %p = validate( @_, {
2397             'fatal' => { type => BOOLEAN, optional => 1, default => 1 },
2398             'verbose' => { type => BOOLEAN, optional => 1, default => $verbose },
2399             'test_ok' => { type => BOOLEAN, optional => 1, },
2400             },
2401             );
2402              
2403 0         0 my $fatal = $p{fatal};
2404 0         0 $verbose = $p{verbose};
2405              
2406 0 0       0 return $p{test_ok} if defined $p{test_ok}; # for testing only
2407              
2408 0         0 my $perlbin = $self->util->find_bin( "perl" );
2409              
2410 0         0 my @targets = ( "$perlbin Makefile.PL", "make", "make install" );
2411 0 0       0 push @targets, "make test" if $verbose;
2412              
2413 0         0 $self->util->install_module_from_src(
2414             'Mysql-Replication',
2415             archive => 'Mysql-Replication.tar.gz',
2416             url => '/internet/sql/mrm',
2417             targets => \@targets,
2418             );
2419             }
2420              
2421             sub munin {
2422 3     3 0 10 my $self = shift;
2423 3         7 my %p = validate( @_, { $self->get_std_opts } );
2424 3 100       18 return $p{test_ok} if defined $p{test_ok}; # for testing
2425              
2426 1 50       2 if ( ! $self->conf->{install_munin} ) {
2427 1         2 $self->audit("skipping munin install (disabled)");
2428 1         3 return;
2429             };
2430              
2431 0         0 $self->rrdtool();
2432              
2433 0 0       0 return $self->audit("no munin install support for $OSNAME")
2434             if $OSNAME ne 'freebsd';
2435              
2436 0         0 $self->freebsd->install_port('p5-Date-Manip');
2437 0         0 $self->munin_node();
2438 0         0 $self->freebsd->install_port('munin-master');
2439              
2440 0         0 return 1;
2441             };
2442              
2443             sub munin_node {
2444 0     0 0 0 my $self = shift;
2445              
2446 0         0 $self->freebsd->install_port('munin-node');
2447 0         0 $self->freebsd->conf_check(
2448             check => "munin_node_enable",
2449             line => 'munin_node_enable="YES"',
2450             );
2451              
2452 0         0 my $locals = '';
2453 0         0 foreach ( @{ $self->util->get_my_ips( exclude_internals => 0 ) } ) {
  0         0  
2454 0         0 my ($a,$b,$c,$d) = split( /\./, $_ );
2455 0         0 $locals .= "allow ^$a\\.$b\\.$c\\.$d" . '$';
2456             };
2457              
2458 0         0 my $munin_etc = '/usr/local/etc/munin';
2459 0         0 $self->config->apply_tweaks(
2460             file => "$munin_etc/munin-node.conf",
2461             changes => [
2462             { search => q{allow ^127\.0\.0\.1$},
2463             replace => q{allow ^127\.0\.0\.1$} . qq{\n$locals\n},
2464             }
2465             ],
2466             );
2467              
2468 0         0 my $qmdir = $self->qmail->get_qmail_dir;
2469 0 0       0 $self->util->file_write( "$munin_etc/plugin-conf.d/plugins.conf",
2470             append => 1,
2471             lines => [ "\n[qmailqstat]\nuser qmails\nenv.qmailstat $qmdir/bin/qmail-qstat"],
2472             ) if ! `grep qmailqstat "$munin_etc/plugin-conf.d/plugins.conf"`;
2473              
2474 0         0 my @setup_links = `/usr/local/sbin/munin-node-configure --suggest --shell`;
2475 0         0 @setup_links = grep {/^ln/} @setup_links;
  0         0  
2476 0         0 @setup_links = grep {!/sendmail_/} @setup_links;
  0         0  
2477 0         0 @setup_links = grep {!/ntp_/} @setup_links;
  0         0  
2478              
2479 0         0 foreach ( @setup_links ) { system $_; };
  0         0  
2480              
2481 0         0 my $t_ver = $Mail::Toaster::VERSION;
2482 0         0 my $dist = "/usr/local/src/Mail-Toaster-$t_ver";
2483 0 0       0 if ( -d $dist ) {
2484 0         0 my @plugins = qw/ qmail_rbl spamassassin /;
2485 0         0 foreach ( @plugins ) {
2486 0         0 copy("$dist/contrib/munin/$_", "$munin_etc/plugins" );
2487 0         0 chmod oct('0755'), "$munin_etc/plugins/$_";
2488             };
2489 0         0 copy ("$dist/contrib/logtail", "/usr/local/bin/logtail");
2490 0         0 chmod oct('0755'), "/usr/local/bin/logtail";
2491             };
2492              
2493 0         0 system "/usr/local/etc/rc.d/munin-node", "restart";
2494             };
2495              
2496             sub nictool {
2497 2     2 0 3 my $self = shift;
2498 2         6 my %p = validate( @_, { $self->get_std_opts, },);
2499              
2500 2 50       15 return $p{test_ok} if defined $p{test_ok}; # for testing
2501              
2502 0         0 $self->conf->{install_expat} = 1; # this must be set for expat to install
2503              
2504 0         0 $self->expat();
2505 0         0 $self->rsync();
2506 0         0 $self->djbdns();
2507 0         0 $self->mysql->install();
2508              
2509             # make sure these perl modules are installed
2510 0         0 $self->util->install_module( "LWP::UserAgent", port => 'p5-libwww' );
2511 0         0 $self->util->install_module( "SOAP::Lite");
2512 0         0 $self->util->install_module( "RPC::XML" );
2513 0         0 $self->util->install_module( "DBI" );
2514 0         0 $self->util->install_module( "DBD::mysql" );
2515              
2516 0         0 $self->util->install_module( "Apache::DBI" );
2517 0         0 $self->util->install_module( "Apache2::SOAP" );
2518              
2519             # install NicTool Server
2520 0         0 my $perlbin = $self->util->find_bin( "perl", fatal => 0 );
2521 0         0 my $version = "NicToolServer-2.06";
2522 0         0 my $http_base = $self->conf->{toaster_http_base};
2523              
2524 0         0 my @targets = ( "$perlbin Makefile.PL", "make", "make install" );
2525              
2526 0         0 push @targets, "make test";
2527              
2528 0 0       0 push @targets, "mv ../$version $http_base"
2529             unless ( -d "$http_base/$version" );
2530              
2531 0 0       0 push @targets, "ln -s $http_base/$version $http_base/NicToolServer"
2532             unless ( -l "$http_base/NicToolServer" );
2533              
2534 0         0 $self->util->install_module_from_src( $version,
2535             archive => "$version.tar.gz",
2536             site => 'http://www.nictool.com',
2537             url => '/download/',
2538             targets => \@targets,
2539             );
2540              
2541             # install NicTool Client
2542 0         0 $version = "NicToolClient-2.06";
2543 0         0 @targets = ( "$perlbin Makefile.PL", "make", "make install" );
2544 0         0 push @targets, "make test";
2545              
2546 0 0       0 push @targets, "mv ../$version $http_base" if ( !-d "$http_base/$version" );
2547 0 0       0 push @targets, "ln -s $http_base/$version $http_base/NicToolClient"
2548             if ( !-l "$http_base/NicToolClient" );
2549              
2550 0         0 $self->util->install_module_from_src( $version,
2551             archive => "$version.tar.gz",
2552             site => 'http://www.nictool.com',
2553             url => '/download/',
2554             targets => \@targets,
2555             );
2556             }
2557              
2558             sub openssl_cert {
2559 0     0 0 0 my $self = shift;
2560              
2561 0         0 my $dir = "/usr/local/openssl/certs";
2562 0         0 my $csr = "$dir/server.csr";
2563 0         0 my $crt = "$dir/server.crt";
2564 0         0 my $key = "$dir/server.key";
2565 0         0 my $pem = "$dir/server.pem";
2566              
2567 0 0       0 $self->util->mkdir_system(dir=>$dir, verbose=>0) if ! -d $dir;
2568              
2569 0         0 my $openssl = $self->util->find_bin('openssl', verbose=>0);
2570 0 0       0 system "$openssl genrsa 2048 > $key" if ! -e $key;
2571 0 0       0 $self->error( "ssl cert key generation failed!") if ! -e $key;
2572              
2573 0 0       0 system "$openssl req -new -key $key -out $csr" if ! -e $csr;
2574 0 0       0 $self->error( "cert sign request ($csr) generation failed!") if ! -e $csr;
2575              
2576 0 0       0 system "$openssl req -x509 -days 999 -key $key -in $csr -out $crt" if ! -e $crt;
2577 0 0       0 $self->error( "cert generation ($crt) failed!") if ! -e $crt;
2578              
2579 0 0       0 system "cat $key $crt > $pem" if ! -e $pem;
2580 0 0       0 $self->error( "pem generation ($pem) failed!") if ! -e $pem;
2581              
2582 0         0 return 1;
2583             };
2584              
2585             sub openssl_conf {
2586 3     3 0 10 my $self = shift;
2587 3         9 my %p = validate( @_, { $self->get_std_opts, },);
2588 3 100       17 return $p{test_ok} if defined $p{test_ok};
2589              
2590 1 50       3 if ( !$self->conf->{install_openssl} ) {
2591 0         0 $self->audit( "openssl: configuring, skipping (disabled)" );
2592 0         0 return;
2593             }
2594              
2595             return if ( defined $self->conf->{install_openssl_conf}
2596 1 50 33     2 && !$self->conf->{install_openssl_conf} );
2597              
2598             # make sure openssl libraries are available
2599 0         0 $self->openssl_install();
2600              
2601 0         0 my $sslconf = $self->openssl_conf_find_config();
2602              
2603             # get/set the settings to alter
2604 0   0     0 my $country = $self->conf->{ssl_country} || "US";
2605 0   0     0 my $state = $self->conf->{ssl_state} || "Texas";
2606 0   0     0 my $org = $self->conf->{ssl_organization} || "DisOrganism, Inc.";
2607 0   0     0 my $locality = $self->conf->{ssl_locality} || "Dallas";
2608             my $name = $self->conf->{ssl_common_name} || $self->conf->{toaster_hostname}
2609 0   0     0 || "mail.example.com";
2610             my $email = $self->conf->{ssl_email_address} || $self->conf->{toaster_admin_email}
2611 0   0     0 || "postmaster\@example.com";
2612              
2613             # update openssl.cnf with our settings
2614 0         0 my $inside;
2615             my $discard;
2616 0         0 my @lines = $self->util->file_read( $sslconf, verbose=>0 );
2617 0         0 foreach my $line (@lines) {
2618              
2619 0 0       0 next if $line =~ /^#/; # comment lines
2620 0 0       0 $inside++ if ( $line =~ /req_distinguished_name/ );
2621 0 0       0 next unless $inside;
2622 0 0 0     0 $discard++ if ( $line =~ /emailAddress_default/ && $line !~ /example\.com/ );
2623              
2624 0 0       0 $line = "countryName_default\t\t= $country"
2625             if $line =~ /^countryName_default/;
2626 0 0       0 $line = "stateOrProvinceName_default\t= $state"
2627             if $line =~ /^stateOrProvinceName_default/;
2628 0 0       0 $line = "localityName\t\t\t= Locality Name (eg, city)\nlocalityName_default\t\t= $locality" if $line =~ /^localityName\s+/;
2629              
2630 0 0       0 $line = "0.organizationName_default\t= $org"
2631             if $line =~ /^0.organizationName_default/;
2632 0 0       0 $line = "commonName_max\t\t\t= 64\ncommonName_default\t\t= $name"
2633             if $line =~ /^commonName_max/;
2634 0 0       0 $line = "emailAddress_max\t\t= 64\nemailAddress_default\t\t= $email"
2635             if $line =~ /^emailAddress_max/;
2636             }
2637              
2638 0 0       0 if ($discard) {
2639 0         0 $self->audit( "openssl: updating $sslconf, ok (no change)" );
2640 0         0 return 2;
2641             }
2642              
2643 0         0 my $tmpfile = "/tmp/openssl.cnf";
2644 0         0 $self->util->file_write( $tmpfile, lines => \@lines, verbose => 0 );
2645 0         0 $self->util->install_if_changed(
2646             newfile => $tmpfile,
2647             existing => $sslconf,
2648             verbose => 0,
2649             );
2650              
2651 0         0 return $self->openssl_cert();
2652             }
2653              
2654             sub openssl_conf_find_config {
2655 0     0 0 0 my $self = shift;
2656              
2657             # figure out where openssl.cnf is
2658 0         0 my $sslconf = "/etc/ssl/openssl.cnf";
2659              
2660 0 0       0 if ( $OSNAME eq "freebsd" ) {
    0          
    0          
2661 0         0 $sslconf = "/etc/ssl/openssl.cnf"; # built-in
2662 0         0 $self->openssl_conf_freebsd( $sslconf );
2663             }
2664             elsif ( $OSNAME eq "darwin" ) {
2665 0         0 $sslconf = "/System/Library/OpenSSL/openssl.cnf";
2666             }
2667             elsif ( $OSNAME eq "linux" ) {
2668 0 0       0 if ( ! -e $sslconf ) {
2669             # centos (and probably RedHat/Fedora)
2670 0         0 $sslconf = "/etc/share/ssl/openssl.cnf";
2671             };
2672             }
2673              
2674 0 0       0 $self->error( "openssl: could not find your openssl.cnf file!") if ! -e $sslconf;
2675 0 0       0 $self->error( "openssl: no write permission to $sslconf!" ) if ! -w $sslconf;
2676              
2677 0         0 $self->audit( "openssl: found $sslconf, ok" );
2678 0         0 return $sslconf;
2679             };
2680              
2681             sub openssl_conf_freebsd {
2682 0     0 0 0 my $self = shift;
2683 0 0       0 my $conf = shift or return;
2684              
2685 0 0 0     0 if ( ! -e $conf && -e '/usr/local/openssl/openssl.cnf.sample' ) {
2686 0         0 mkpath "/etc/ssl";
2687 0         0 system "cp /usr/local/openssl/openssl.cnf.sample $conf";
2688             };
2689              
2690 0 0       0 if ( -d "/usr/local/openssl" ) {
2691 0 0       0 if ( ! -e "/usr/local/openssl/openssl.cnf" ) {
2692 0         0 symlink($conf, "/usr/local/openssl/openssl.cnf");
2693             };
2694             };
2695             };
2696              
2697             sub openssl_get_ciphers {
2698 0     0 0 0 my $self = shift;
2699 0         0 my $ciphers = shift;
2700 0         0 my $openssl = $self->util->find_bin( 'openssl', verbose=>0 );
2701              
2702 0 0       0 my $s = $ciphers eq 'all' ? 'ALL'
    0          
    0          
    0          
2703             : $ciphers eq 'high' ? 'HIGH:!SSLv2'
2704             : $ciphers eq 'medium' ? 'HIGH:MEDIUM:!SSLv2'
2705             : $ciphers eq 'pci' ? 'DEFAULT:!ADH:!LOW:!EXP:!SSLv2:+HIGH:+MEDIUM'
2706             : 'DEFAULT';
2707 0         0 $ciphers = `$openssl ciphers $s`;
2708 0         0 chomp $ciphers;
2709 0         0 return $ciphers;
2710             };
2711              
2712             sub openssl_install {
2713 0     0 0 0 my $self = shift;
2714              
2715 0 0       0 return if ! $self->conf->{install_openssl};
2716              
2717 0 0       0 if ( $OSNAME eq 'freebsd' ) {
2718 0 0       0 if (!$self->freebsd->is_port_installed( 'openssl' ) ) {
2719 0         0 $self->openssl_install_freebsd();
2720             };
2721             }
2722             else {
2723 0         0 my $bin = $self->util->find_bin('openssl',verbose=>0,fatal=>0);
2724 0 0       0 if ( ! $bin ) {
2725 0         0 warn "no openssl support for OS $OSNAME, please install manually.\n";
2726             }
2727             else {
2728 0         0 warn "using detected openssl on $OSNAME.\n";
2729             };
2730             };
2731             };
2732              
2733             sub openssl_install_freebsd {
2734 0     0 0 0 my $self = shift;
2735              
2736 0 0       0 if ($self->freebsd->install_package('openssl')) {
2737 0         0 return 1;
2738             }
2739              
2740 0         0 return $self->freebsd->install_port( 'openssl',
2741             category=> 'security',
2742             options => "# Options for openssl-1.0.1_8
2743             _OPTIONS_READ=openssl-1.0.1_8
2744             _FILE_COMPLETE_OPTIONS_LIST=SHARED THREADS I386 SSE2 ASM PADLOCK ZLIB SCTP MD2 RC5 RFC3779 GMP EC
2745             OPTIONS_FILE_SET+=SHARED
2746             OPTIONS_FILE_SET+=THREADS
2747             OPTIONS_FILE_UNSET+=I386
2748             OPTIONS_FILE_SET+=SSE2
2749             OPTIONS_FILE_SET+=ASM
2750             OPTIONS_FILE_UNSET+=PADLOCK
2751             OPTIONS_FILE_SET+=ZLIB
2752             OPTIONS_FILE_UNSET+=SCTP
2753             OPTIONS_FILE_UNSET+=MD2
2754             OPTIONS_FILE_UNSET+=RC5
2755             OPTIONS_FILE_UNSET+=RFC3779
2756             OPTIONS_FILE_UNSET+=GMP
2757             OPTIONS_FILE_SET+=EC
2758             ",
2759             );
2760             };
2761              
2762             sub periodic_conf {
2763              
2764 0 0   0 0 0 return if -e "/etc/periodic.conf";
2765              
2766 0         0 open my $PERIODIC, '>>', '/etc/periodic.conf';
2767 0         0 print $PERIODIC '
2768             #--periodic.conf--
2769             # 210.backup-aliases
2770             daily_backup_aliases_enable="NO" # Backup mail aliases
2771              
2772             # 440.status-mailq
2773             daily_status_mailq_enable="YES" # Check mail status
2774             daily_status_mailq_shorten="NO" # Shorten output
2775             daily_status_include_submit_mailq="NO" # Also submit queue
2776              
2777             # 460.status-mail-rejects
2778             daily_status_mail_rejects_enable="NO" # Check mail rejects
2779             daily_status_mail_rejects_logs=3 # How many logs to check
2780             #-- end --
2781             ';
2782 0         0 close $PERIODIC;
2783             }
2784              
2785             sub php {
2786 0     0 0 0 my $self = shift;
2787              
2788 0 0 0     0 if ( ! $self->conf->{install_squirrelmail} && ! $self->conf->{install_roundcube} ) {
2789 0         0 $self->audit("skipping PHP install");
2790 0         0 return;
2791             };
2792              
2793 0 0       0 if ( $OSNAME eq 'freebsd' ) {
2794 0         0 return $self->php_freebsd;
2795             };
2796              
2797 0         0 my $php = $self->util->find_bin('php',fatal=>0);
2798 0         0 $self->error( "no php install support for $OSNAME yet, and php is not installed. Please install and try again." );
2799 0         0 return;
2800             };
2801              
2802             sub php_freebsd {
2803 0     0 0 0 my $self = shift;
2804              
2805 0 0       0 $self->freebsd->install_port( "php5",
2806             category=> 'lang',
2807             options => "# This file generated by mail-toaster
2808             # Options for php5-5.4.16
2809             _OPTIONS_READ=php5-5.4.16
2810             _FILE_COMPLETE_OPTIONS_LIST=CLI CGI FPM APACHE AP2FILTER EMBED DEBUG DTRACE IPV6 MAILHEAD LINKTHR
2811             OPTIONS_FILE_SET+=CLI
2812             OPTIONS_FILE_SET+=CGI
2813             OPTIONS_FILE_UNSET+=FPM
2814             OPTIONS_FILE_UNSET+=APACHE
2815             OPTIONS_FILE_UNSET+=AP2FILTER
2816             OPTIONS_FILE_UNSET+=EMBED
2817             OPTIONS_FILE_UNSET+=DEBUG
2818             OPTIONS_FILE_UNSET+=DTRACE
2819             OPTIONS_FILE_SET+=IPV6
2820             OPTIONS_FILE_UNSET+=MAILHEAD
2821             OPTIONS_FILE_UNSET+=LINKTHR
2822             ",
2823             ) or return;
2824              
2825 0         0 my $config = "/usr/local/etc/php.ini";
2826 0 0       0 if ( ! -e $config ) {
2827 0 0       0 copy("$config-production", $config) if -e "$config-production";
2828 0         0 chmod oct('0644'), $config;
2829              
2830 0         0 $self->config->apply_tweaks(
2831             file => "/usr/local/etc/php.ini",
2832             changes => [
2833             { search => q{;include_path = ".:/php/includes"},
2834             replace => q{include_path = ".:/usr/local/share/pear"},
2835             },
2836             { search => q{;date.timezone =},
2837             replace => q{date.timezone = America/Denver},
2838             },
2839             ],
2840             );
2841             };
2842              
2843 0 0       0 return 1 if -f $config;
2844 0         0 return;
2845             };
2846              
2847             sub phpmyadmin {
2848 0     0 0 0 my $self = shift;
2849 0         0 my %p = validate( @_, { $self->get_std_opts },);
2850              
2851 0 0       0 return $p{test_ok} if defined $p{test_ok}; # for testing only
2852              
2853 0 0       0 unless ( $self->conf->{install_phpmyadmin} ) {
2854 0         0 print "phpMyAdmin install disabled. Set install_phpmyadmin in "
2855             . "toaster-watcher.conf if you want to install it.\n";
2856 0         0 return 0;
2857             }
2858              
2859             # prevent t1lib from installing X11
2860 0 0       0 if ( $OSNAME eq "freebsd" ) {
2861 0         0 $self->php();
2862 0         0 $self->freebsd->install_port( "t1lib", flags => "WITHOUT_X11=yes" );
2863 0         0 $self->freebsd->install_port( "php5-gd" );
2864             }
2865              
2866 0         0 $self->mysql->phpmyadmin_install;
2867             }
2868              
2869             sub portmaster {
2870 0     0 0 0 my $self = shift;
2871              
2872 0 0       0 if ( ! $self->conf->{install_portmaster} ) {
2873 0         0 $self->audit("install portmaster skipped, not selected", verbose=>1);
2874 0         0 return;
2875             };
2876              
2877 0         0 $self->freebsd->install_port( "portmaster" );
2878             };
2879              
2880             sub ports {
2881 0     0 0 0 my $self = shift;
2882 0         0 my %p = validate( @_, { $self->get_std_opts },);
2883              
2884 0 0       0 return $self->freebsd->update_ports() if $OSNAME eq "freebsd";
2885 0 0       0 return $self->darwin->update_ports() if $OSNAME eq "darwin";
2886              
2887 0         0 print "Sorry, no ports support for $OSNAME yet.\n";
2888 0         0 return;
2889             }
2890              
2891             sub qmailadmin {
2892 3     3 0 10 my $self = shift;
2893 3         6 my %p = validate( @_, { $self->get_std_opts } );
2894              
2895 3 100       17 return $p{test_ok} if defined $p{test_ok};
2896              
2897 1 50       2 my $ver = $self->conf->{install_qmailadmin} or do {
2898 1         2 $self->audit( "skipping qmailadmin install, it's not selected!");
2899 1         2 return;
2900             };
2901              
2902 0         0 my $package = "qmailadmin-$ver";
2903 0         0 my $site = "http://" . $self->conf->{toaster_sf_mirror};
2904 0         0 my $url = "/qmailadmin/qmailadmin-stable/$ver";
2905              
2906 0         0 my $toaster = $self->conf->{toaster_dl_site}.$self->conf->{toaster_dl_url};
2907 0   0     0 $toaster ||= "http://mail-toaster.org";
2908              
2909 0         0 my $cgi = $self->conf->{toaster_cgi_bin};
2910              
2911 0         0 my $docroot = $self->conf->{toaster_http_docs};
2912              
2913 0         0 my ($help);
2914 0 0       0 $help++ if $self->conf->{qmailadmin_help_links};
2915              
2916 0 0       0 if ( $ver eq "port" ) {
2917 0 0       0 if ( $OSNAME ne "freebsd" ) {
2918 0         0 print
2919             "FAILURE: Sorry, no port install of qmailadmin (yet). Please edit
2920             toaster-watcher.conf and select a version of qmailadmin to install.\n";
2921 0         0 return 0;
2922             }
2923              
2924 0         0 $self->qmailadmin_freebsd_port();
2925 0 0       0 $self->qmailadmin_help() if $help;
2926 0         0 return 1;
2927             }
2928              
2929 0         0 my $conf_args;
2930              
2931 0 0       0 if ( -x "$cgi/qmailadmin" ) {
2932 0 0       0 return 0
2933             unless $self->util->yes_or_no(
2934             "qmailadmin is installed, do you want to reinstall?",
2935             timeout => 60,
2936             );
2937             }
2938              
2939 0 0       0 if ( $self->conf->{qmailadmin_domain_autofill} ) {
2940 0         0 $conf_args = " --enable-domain-autofill=Y";
2941 0         0 print "domain autofill: yes\n";
2942             }
2943              
2944 0 0       0 if ( $self->util->yes_or_no( "\nDo you want spam options? " ) ) {
2945             $conf_args .=
2946             " --enable-modify-spam=Y"
2947             . " --enable-spam-command=\""
2948 0         0 . $self->conf->{qmailadmin_spam_command} . "\"";
2949             }
2950              
2951 0 0       0 if ( $self->conf->{qmailadmin_modify_quotas} ) {
2952 0         0 $conf_args .= " --enable-modify-quota=y";
2953 0         0 print "modify quotas: yes\n";
2954             }
2955              
2956 0 0       0 if ( $self->conf->{qmailadmin_install_as_root} ) {
2957 0         0 $conf_args .= " --enable-vpopuser=root";
2958 0         0 print "install as root: yes\n";
2959             }
2960              
2961 0         0 $conf_args .= " --enable-autoresponder-path=".$self->conf->{toaster_prefix}."/bin";
2962              
2963 0 0       0 if ( defined $self->conf->{qmailadmin_catchall} ) {
2964 0 0       0 $conf_args .= " --disable-catchall" if ! $self->conf->{qmailadmin_catchall};
2965             };
2966              
2967 0 0       0 if ( $self->conf->{qmailadmin_help_links} ) {
2968 0         0 $conf_args .= " --enable-help=y";
2969 0         0 $help = 1;
2970             }
2971              
2972 0 0       0 if ( $OSNAME eq "darwin" ) {
2973 0         0 my $vpopdir = $self->vpopmail->get_vpop_dir;
2974 0         0 $self->util->syscmd( "ranlib $vpopdir/lib/libvpopmail.a", verbose => 0 );
2975             }
2976              
2977 0   0     0 my $make = $self->util->find_bin( "gmake", fatal=>0, verbose=>0) ||
2978             $self->util->find_bin( "make", verbose=>0 );
2979              
2980 0         0 $self->util->install_from_source(
2981             package => $package,
2982             site => $site,
2983             url => $url,
2984             targets =>
2985             [ "./configure " . $conf_args, "$make", "$make install-strip" ],
2986             source_sub_dir => 'mail',
2987             );
2988              
2989 0 0       0 $self->qmailadmin_help() if $help;
2990              
2991 0         0 return 1;
2992             }
2993              
2994             sub qmailadmin_help {
2995 0     0 0 0 my $self = shift;
2996              
2997 0 0       0 my $ver = $self->conf->{qmailadmin_help_links} or return;
2998 0         0 my $docroot = $self->conf->{toaster_http_docs};
2999 0         0 my $helpdir = $docroot . "/qmailadmin/images/help";
3000              
3001 0 0       0 if ( -d $helpdir ) {
3002 0         0 $self->audit( "qmailadmin: installing help files, ok (exists)" );
3003 0         0 return 1;
3004             }
3005              
3006 0   0     0 my $src = $self->conf->{toaster_src_dir} || "/usr/local/src";
3007 0         0 $src .= "/mail";
3008              
3009 0         0 print "qmailadmin: Installing help files in $helpdir\n";
3010 0         0 $self->util->cwd_source_dir( $src );
3011              
3012 0         0 my $helpfile = "qmailadmin-help-$ver";
3013 0 0       0 unless ( -e "$helpfile.tar.gz" ) {
3014             $self->util->get_url(
3015 0         0 "http://".$self->conf->{toaster_sf_mirror}."/qmailadmin/qmailadmin-help/$ver/$helpfile.tar.gz"
3016             );
3017             }
3018              
3019 0 0       0 if ( !-e "$helpfile.tar.gz" ) {
3020 0         0 carp "qmailadmin: FAILED: help files couldn't be downloaded!\n";
3021 0         0 return;
3022             }
3023              
3024 0         0 $self->util->extract_archive( "$helpfile.tar.gz" );
3025              
3026 0 0       0 move( $helpfile, $helpdir ) or
3027             $self->error( "Could not move $helpfile to $helpdir");
3028              
3029 0         0 $self->audit( "qmailadmin: installed help files, ok" );
3030             }
3031              
3032             sub qmailadmin_freebsd_port {
3033 0     0 0 0 my $self = shift;
3034 0         0 my $conf = $self->conf;
3035              
3036 0 0       0 my $help = $conf->{qmailadmin_help_links} ? 'SET' : 'UNSET';
3037 0 0       0 my $catchall = $conf->{qmailadmin_catchall} ? 'SET' : 'UNSET';
3038 0 0       0 my $quotam = $conf->{qmailadmin_modify_quotas} ? 'SET' : 'UNSET';
3039 0 0       0 my $domauto = $conf->{qmailadmin_domain_autofill} ? 'SET' : 'UNSET';
3040 0 0       0 my $spam = $conf->{qmailadmin_spam_option} ? 'SET' : 'UNSET';
3041              
3042 0         0 my @args;
3043              
3044             push @args, 'QMAIL_DIR="'.$conf->{qmail_dir}.'"'
3045 0 0       0 if $conf->{qmail_dir} ne '/var/qmail';
3046              
3047 0 0 0     0 if ( $spam eq 'SET' && $conf->{qmailadmin_spam_command} ) {
3048 0         0 push @args, 'SPAM_COMMAND="'.$conf->{qmailadmin_spam_command}.'"';
3049             }
3050              
3051 0         0 $self->freebsd->install_port( "qmailadmin",
3052             flags => join( ',', @args ),
3053             options => "# This file installed by mail::toaster
3054             # Options for qmailadmin-1.2.15_5,2
3055             _OPTIONS_READ=qmailadmin-1.2.15_5,2
3056             _FILE_COMPLETE_OPTIONS_LIST=CATCHALL DOMAIN_AUTOFILL HELP IDX IDX_SQL IPAUTH MODIFY_QUOTA NOCACHE SPAM_DETECTION SPAM_NEEDS_EMAIL TRIVIAL_PASSWORD USER_INDEX
3057             OPTIONS_FILE_$catchall+=CATCHALL
3058             OPTIONS_FILE_SET+=DOMAIN_AUTOFILL
3059             OPTIONS_FILE_$help+=HELP
3060             OPTIONS_FILE_SET+=IDX
3061             OPTIONS_FILE_UNSET+=IDX_SQL
3062             OPTIONS_FILE_SET+=IPAUTH
3063             OPTIONS_FILE_$quotam+=MODIFY_QUOTA
3064             OPTIONS_FILE_UNSET+=NOCACHE
3065             OPTIONS_FILE_$spam+=SPAM_DETECTION
3066             OPTIONS_FILE_UNSET+=SPAM_NEEDS_EMAIL
3067             OPTIONS_FILE_SET+=TRIVIAL_PASSWORD
3068             OPTIONS_FILE_SET+=USER_INDEX
3069             ",
3070             );
3071              
3072 0 0       0 if ( $conf->{qmailadmin_install_as_root} ) {
3073 0         0 my $gid = getgrnam("vchkpw");
3074 0         0 chown( 0, $gid, "/usr/local/www/cgi-bin.default/qmailadmin/qmailadmin" );
3075             }
3076             }
3077              
3078             sub qpsmtpd {
3079 0     0 0 0 my $self = shift;
3080              
3081             # install Qmail::Deliverable
3082             # install vpopmaild service
3083              
3084             # install qpsmtpd
3085 0         0 print '
3086             - git clone https://github.com/qpsmtpd-dev/qpsmtpd-dev
3087             - cp -r config.sample config
3088             - chown smtpd:smtpd qpsmtpd
3089             - chmod +s qpsmtpd
3090             ';
3091              
3092             # install qpsmtpd service
3093 0         0 print '
3094             - services stop
3095             - rm /var/service/smtp
3096             - stop toaster-watcher and do previous step again
3097             - ln -s /usr/local/src/qpsmtpd-dev/ /var/serivces/qpsmtpd
3098             - cp /var/qmail/supervise/smtp/log/run log/run
3099             ';
3100              
3101             # install qpsmtpd SSL certs
3102 0         0 print '
3103             - add clamav user to smtpd user group
3104             - echo 0770 > config/spool_perms # Hmmmm... quite open.. how did we do
3105             this with current toaster? clamav needs to read vpopmail files
3106             - echo /var/spool/clamd > spool_dir
3107             - edits in config/plugins
3108             - disable: ident/geoip
3109             - disable: quit_fortune
3110             - enable: auth/auth_checkpassword
3111             checkpw /usr/local/vpopmail/bin/vchkpw true /usr/bin/true
3112             - disable: auth/auth_flat_file
3113             - disable: dspam learn_from_sa 7 reject 1
3114             - enable: virus/clamdscan deny_viruses yes
3115             clamd_socket /var/run/clamav/clamd.sock max_size 3072
3116             - enable: queue/qmail-queue
3117             - enable: sender_permitted_from
3118             - install Qmail::Deliverable
3119             - enable: qmail_deliverable
3120             - install clamav::client
3121             - edit run file QPUSER=vpopmail
3122             - services start
3123             - clamdscan plugin modification:
3124             ';
3125             };
3126              
3127             sub razor {
3128 3     3 0 8 my $self = shift;
3129 3         10 my %p = validate( @_, { $self->get_std_opts },);
3130              
3131 3 100       12 my $ver = $self->conf->{install_razor} or do {
3132 1         3 $self->audit( "razor: installing, skipping (disabled)" );
3133 1         3 return;
3134             };
3135              
3136 2 50       9 return $p{test_ok} if defined $p{test_ok}; # for testing
3137              
3138 0         0 $self->util->install_module( "Digest::Nilsimsa" );
3139 0         0 $self->util->install_module( "Digest::SHA1" );
3140              
3141 0 0       0 if ( $ver eq "port" ) {
3142 0 0       0 if ( $OSNAME eq "freebsd" ) {
    0          
3143 0         0 $self->freebsd->install_port( "razor-agents" );
3144             }
3145             elsif ( $OSNAME eq "darwin" ) {
3146             # old ports tree, deprecated
3147 0         0 $self->darwin->install_port( "razor" );
3148             # this one should work
3149 0         0 $self->darwin->install_port( "p5-razor-agents" );
3150             }
3151             }
3152              
3153 0 0       0 if ( $self->util->find_bin( "razor-client", fatal => 0 ) ) {
3154 0         0 print "It appears you have razor installed, skipping manual build.\n";
3155 0         0 $self->razor_config();
3156 0         0 return 1;
3157             }
3158              
3159 0 0 0     0 $ver = "2.80" if ( $ver == 1 || $ver eq "port" );
3160              
3161 0         0 $self->util->install_module_from_src( 'razor-agents-' . $ver,
3162             archive => 'razor-agents-' . $ver . '.tar.gz',
3163             site => 'http://umn.dl.sourceforge.net/sourceforge',
3164             url => '/razor',
3165             );
3166              
3167 0         0 $self->razor_config();
3168 0         0 return 1;
3169             }
3170              
3171             sub razor_config {
3172 0     0 0 0 my $self = shift;
3173              
3174 0         0 print "razor: beginning configuration.\n";
3175              
3176 0 0       0 if ( -d "/etc/razor" ) {
3177 0         0 print "razor_config: it appears you have razor configured, skipping.\n";
3178 0         0 return 1;
3179             }
3180              
3181 0         0 my $client = $self->util->find_bin( "razor-client", fatal => 0 );
3182 0         0 my $admin = $self->util->find_bin( "razor-admin", fatal => 0 );
3183              
3184             # for old versions of razor
3185 0 0 0     0 if ( -x $client && !-x $admin ) {
3186 0         0 $self->util->syscmd( $client, verbose=>0 );
3187             }
3188              
3189 0 0       0 unless ( -x $admin ) {
3190 0         0 print "FAILED: couldn't find $admin!\n";
3191 0         0 return 0;
3192             }
3193              
3194 0         0 $self->util->syscmd( "$admin -home=/etc/razor -create -d", verbose=>0 );
3195 0         0 $self->util->syscmd( "$admin -home=/etc/razor -register -d", verbose=>0 );
3196              
3197 0         0 my $file = "/etc/razor/razor-agent.conf";
3198 0 0       0 if ( -e $file ) {
3199 0         0 my @lines = $self->util->file_read( $file );
3200 0         0 foreach my $line (@lines) {
3201 0 0       0 if ( $line =~ /^logfile/ ) {
3202 0         0 $line = 'logfile = /var/log/razor-agent.log';
3203             }
3204             }
3205 0         0 $self->util->file_write( $file, lines => \@lines, verbose=>0 );
3206             }
3207              
3208 0         0 $file = "/etc/newsyslog.conf";
3209 0 0       0 if ( -e $file ) {
3210 0 0       0 if ( !`grep razor-agent $file` ) {
3211 0         0 $self->util->file_write( $file,
3212             lines => ["/var/log/razor-agent.log 600 5 1000 * Z"],
3213             append => 1,
3214             verbose => 0,
3215             );
3216             }
3217             }
3218              
3219 0         0 print "razor: configuration completed.\n";
3220 0         0 return 1;
3221             }
3222              
3223             sub refresh_config {
3224 0     0 0 0 my ($self, $file_path) = @_;
3225              
3226 0 0       0 if ( ! -f $file_path ) {
3227 0         0 $self->audit( "config: $file_path is missing!, FAILED" );
3228 0         0 return;
3229             };
3230              
3231 0 0       0 warn "found: $file_path \n" if $self->{verbose};
3232              
3233             # refresh our $conf
3234             my $conf = $self->util->parse_config( $file_path,
3235             verbose => $self->{verbose},
3236             fatal => $self->{fatal},
3237 0         0 );
3238              
3239 0         0 $self->set_config($conf);
3240              
3241 0 0       0 warn "refreshed \$conf from: $file_path \n" if $self->{verbose};
3242 0         0 return $conf;
3243             };
3244              
3245             sub ripmime {
3246 0     0 0 0 my $self = shift;
3247 0         0 my %p = validate( @_, { $self->get_std_opts },);
3248              
3249 0 0       0 return $p{test_ok} if defined $p{test_ok}; # for testing
3250              
3251 0         0 my $ver = $self->conf->{install_ripmime};
3252 0 0       0 if ( !$ver ) {
3253 0         0 print "ripmime install not selected.\n";
3254 0         0 return 0;
3255             }
3256              
3257 0         0 print "rimime: installing...\n";
3258              
3259 0 0 0     0 if ( $ver eq "port" || $ver eq "1" ) {
3260              
3261 0 0       0 if ( $self->util->find_bin( "ripmime", fatal => 0 ) ) {
3262 0         0 print "ripmime: already installed...done.\n\n";
3263 0         0 return 1;
3264             }
3265              
3266 0 0       0 if ( $OSNAME eq "freebsd" ) {
    0          
3267 0 0       0 $self->freebsd->install_port( "ripmime" ) and return 1;
3268             }
3269             elsif ( $OSNAME eq "darwin" ) {
3270 0 0       0 $self->darwin->install_port( "ripmime" ) and return 1;
3271             }
3272              
3273 0 0       0 if ( $self->util->find_bin( "ripmime", fatal => 0 ) ) {
3274 0         0 print "ripmime: ripmime has been installed successfully.\n";
3275 0         0 return 1;
3276             }
3277              
3278 0         0 $ver = "1.4.0.6";
3279             }
3280              
3281 0         0 my $ripmime = $self->util->find_bin( "ripmime", fatal => 0 );
3282 0 0       0 if ( -x $ripmime ) {
3283 0         0 my $installed = `$ripmime -V`;
3284 0         0 ($installed) = $installed =~ /v(.*) - /;
3285              
3286 0 0       0 if ( $ver eq $installed ) {
3287 0         0 print "ripmime: version ($ver) is already installed!\n";
3288 0         0 return 1;
3289             }
3290             }
3291              
3292             $self->util->install_from_source(
3293 0         0 package => "ripmime-$ver",
3294             site => 'http://www.pldaniels.com',
3295             url => '/ripmime',
3296             targets => [ 'make', 'make install' ],
3297             bintest => 'ripmime',
3298             verbose => 1,
3299             source_sub_dir => 'mail',
3300             );
3301             }
3302              
3303             sub rrdtool {
3304 0     0 0 0 my $self = shift;
3305 0         0 my %p = validate( @_, { $self->get_std_opts },);
3306 0 0       0 return $p{test_ok} if defined $p{test_ok}; # for testing
3307              
3308 0 0       0 unless ( $self->conf->{install_rrdutil} ) {
3309 0         0 print "install_rrdutil is not set in toaster-watcher.conf! Skipping.\n";
3310 0         0 return;
3311             }
3312              
3313 0 0       0 if ( $OSNAME eq "freebsd" ) {
    0          
3314              
3315             # the newer (default) version of rrdtool requires an obscene amount
3316             # of x11 software be installed. Install the older one instead.
3317 0         0 $self->freebsd->install_port('rrdtool',
3318             dir => 'rrdtool12',
3319             options => "#\n# Options for rrdtool-1.2.30_1
3320             _OPTIONS_READ=rrdtool-1.2.30_1
3321             WITHOUT_PYTHON_MODULE=true
3322             WITHOUT_RUBY_MODULE=true
3323             WITH_PERL_MODULE=true\n",
3324             );
3325             }
3326             elsif ( $OSNAME eq "darwin" ) {
3327 0         0 $self->darwin->port_install( port_name => "rrdtool" );
3328             }
3329              
3330 0 0       0 return 1 if -x $self->util->find_bin( 'rrdtool', fatal => 0 );
3331              
3332 0         0 $self->util->install_from_source(
3333             package => "rrdtool-1.2.23",
3334             site => 'http://people.ee.ethz.ch',
3335             url => '/~oetiker/webtools/rrdtool/pub',
3336             targets => [ './configure', 'make', 'make install' ],
3337             patches => [ ],
3338             bintest => 'rrdtool',
3339             verbose => 1,
3340             );
3341             }
3342              
3343             sub roundcube {
3344 3     3 0 11 my $self = shift;
3345 3         7 my %p = validate( @_, { $self->get_std_opts },);
3346              
3347 3 100       17 return $p{test_ok} if defined $p{test_ok}; # for testing
3348              
3349 1 50       2 if ( ! $self->conf->{install_roundcube} ) {
3350 1         2 $self->audit( "not installing roundcube, not selected!" );
3351 1         3 return;
3352             };
3353              
3354 0 0       0 if ( $OSNAME eq "freebsd" ) {
3355 0 0       0 $self->php() or return;
3356 0 0       0 $self->roundcube_freebsd() or return;
3357             }
3358             else {
3359 0         0 print
3360             "please install roundcube manually. Support for install on $OSNAME is not available yet.\n";
3361 0         0 return;
3362             }
3363              
3364 0         0 return 1;
3365             }
3366              
3367             sub roundcube_freebsd {
3368 0     0 0 0 my $self = shift;
3369              
3370 0         0 $self->sqlite_freebsd();
3371              
3372 0 0       0 $self->freebsd->install_port( "roundcube",
3373             category=> 'mail',
3374             options => "# Options for roundcube-0.9.2,1
3375             _OPTIONS_READ=roundcube-0.9.2,1
3376             _FILE_COMPLETE_OPTIONS_LIST=GD LDAP NSC PSPELL SSL MYSQL PGSQL SQLITE
3377             OPTIONS_FILE_UNSET+=GD
3378             OPTIONS_FILE_UNSET+=LDAP
3379             OPTIONS_FILE_UNSET+=NSC
3380             OPTIONS_FILE_UNSET+=PSPELL
3381             OPTIONS_FILE_SET+=SSL
3382             OPTIONS_FILE_UNSET+=MYSQL
3383             OPTIONS_FILE_UNSET+=PGSQL
3384             OPTIONS_FILE_SET+=SQLITE
3385             ",
3386             ) or return;
3387              
3388 0         0 $self->roundcube_config();
3389             };
3390              
3391             sub roundcube_config {
3392 0     0 0 0 my $self = shift;
3393 0         0 my $rcdir = "/usr/local/www/roundcube";
3394 0         0 my $config = "$rcdir/config";
3395              
3396 0         0 foreach my $c ( qw/ db.inc.php main.inc.php / ) {
3397 0 0       0 copy( "$config/$c.dist", "$config/$c" ) if ! -e "$config/$c";
3398             };
3399              
3400 0 0       0 if ( ! -f "$config/db.inc.php" ) {
3401 0         0 warn "unable to find roundcube/config/db.inc.php. Edit it with appropriate DSN settings\n";
3402 0         0 return;
3403             };
3404              
3405 0         0 $self->config->apply_tweaks(
3406             file => "$config/main.inc.php",
3407             changes => [
3408             { search => q{$rcmail_config['default_host'] = '';},
3409             replace => q{$rcmail_config['default_host'] = 'localhost';},
3410             },
3411             { search => q{$rcmail_config['session_lifetime'] = 10;},
3412             replace => q{$rcmail_config['session_lifetime'] = 30;},
3413             },
3414             { search => q{$rcmail_config['imap_auth_type'] = null;},
3415             replace => q{$rcmail_config['imap_auth_type'] = plain;},
3416             },
3417             ],
3418             );
3419              
3420 0         0 return $self->roundcube_config_sqlite();
3421             };
3422              
3423             sub roundcube_config_sqlite {
3424 0     0 0 0 my $self = shift;
3425              
3426 0         0 my $rcdir = "/usr/local/www/roundcube";
3427 0         0 my $config = "$rcdir/config/db.inc.php";
3428              
3429 0         0 my $spool = '/var/spool/roundcubemail';
3430 0         0 mkpath $spool;
3431 0         0 my (undef,undef,$uid,$gid) = getpwnam('www');
3432 0         0 chown $uid, $gid, $spool;
3433              
3434             # configure roundcube to use sqlite for DB
3435 0         0 $self->config->apply_tweaks(
3436             file => $config,
3437             changes => [
3438             { search => q{$rcmail_config['db_dsnw'] = 'mysql://roundcube:pass@localhost/roundcubemail';},
3439             replace => q{$rcmail_config['db_dsnw'] = 'sqlite:////var/spool/roundcubemail/sqlite.db?mode=0646';},
3440             },
3441             ],
3442             );
3443             };
3444              
3445             sub rsync {
3446 0     0 0 0 my $self = shift;
3447 0         0 my %p = validate( @_, { $self->get_std_opts },);
3448              
3449 0 0       0 return $p{test_ok} if defined $p{test_ok}; # for testing
3450              
3451 0 0       0 if ( $OSNAME eq "freebsd" ) {
    0          
3452 0         0 $self->freebsd->install_port( "rsync",
3453             options => "#\n
3454             # This file was generated by mail-toaster
3455             # Options for rsync-3.0.9_3
3456             _OPTIONS_READ=rsync-3.0.9_3
3457             _FILE_COMPLETE_OPTIONS_LIST=ACL ATIMES DOCS FLAGS ICONV POPT_PORT RENAMED SSH TIMELIMIT
3458             OPTIONS_FILE_UNSET+=ACL
3459             OPTIONS_FILE_UNSET+=ATIMES
3460             OPTIONS_FILE_SET+=DOCS
3461             OPTIONS_FILE_UNSET+=FLAGS
3462             OPTIONS_FILE_UNSET+=ICONV
3463             OPTIONS_FILE_UNSET+=POPT_PORT
3464             OPTIONS_FILE_UNSET+=RENAMED
3465             OPTIONS_FILE_SET+=SSH
3466             OPTIONS_FILE_UNSET+=TIMELIMIT\n",
3467             );
3468             }
3469             elsif ( $OSNAME eq "darwin" ) {
3470 0         0 $self->darwin->install_port( "rsync" );
3471             }
3472             else {
3473 0         0 die
3474             "please install rsync manually. Support for $OSNAME is not available yet.\n";
3475             }
3476              
3477 0         0 return $self->util->find_bin('rsync',verbose=>0);
3478             }
3479              
3480             sub set_config {
3481 0     0 0 0 my $self = shift;
3482 0         0 my $newconf = shift;
3483 0 0       0 return $self->conf if ! $newconf;
3484 0         0 $self->conf( $newconf );
3485 0         0 return $newconf;
3486             };
3487              
3488             sub simscan {
3489 0     0 0 0 require Mail::Toaster::Setup::Simscan;
3490 0         0 return Mail::Toaster::Setup::Simscan->new;
3491             }
3492              
3493             sub socklog {
3494 0     0 0 0 my $self = shift;
3495 0         0 my %p = validate( @_, { 'ip' => SCALAR, $self->get_std_opts, },);
3496              
3497 0         0 my $ip = $p{ip};
3498              
3499 0   0     0 my $user = $self->conf->{qmail_log_user} || "qmaill";
3500 0   0     0 my $group = $self->conf->{qmail_log_group} || "qnofiles";
3501              
3502 0         0 my $uid = getpwnam($user);
3503 0         0 my $gid = getgrnam($group);
3504              
3505 0         0 my $logdir = $self->conf->{qmail_log_base};
3506 0 0       0 unless ( -d $logdir ) { $logdir = "/var/log/mail" }
  0         0  
3507              
3508 0 0       0 if ( $OSNAME eq "freebsd" ) {
3509 0         0 $self->freebsd->install_port( "socklog" );
3510             }
3511             else {
3512 0         0 print "\n\nNOTICE: Be sure to install socklog!!\n\n";
3513             }
3514 0         0 $self->socklog_qmail_control( 'send', $ip, $user, $logdir );
3515 0         0 $self->socklog_qmail_control( 'smtp', $ip, $user, $logdir );
3516 0         0 $self->socklog_qmail_control( 'pop3', $ip, $user, $logdir );
3517              
3518 0 0       0 unless ( -d $logdir ) {
3519 0 0       0 mkdir( $logdir, oct('0755') ) or croak "socklog: couldn't create $logdir: $!";
3520 0 0       0 chown( $uid, $gid, $logdir ) or croak "socklog: couldn't chown $logdir: $!";
3521             }
3522              
3523 0         0 foreach my $prot (qw/ send smtp pop3 /) {
3524 0 0       0 unless ( -d "$logdir/$prot" ) {
3525 0 0       0 mkdir( "$logdir/$prot", oct('0755') )
3526             or croak "socklog: couldn't create $logdir/$prot: $!";
3527             }
3528 0 0       0 chown( $uid, $gid, "$logdir/$prot" )
3529             or croak "socklog: couldn't chown $logdir/$prot: $!";
3530             }
3531             }
3532              
3533             sub socklog_qmail_control {
3534 0     0 0 0 my ( $self, $serv, $ip, $user, $log ) = @_;
3535              
3536 0   0     0 $ip ||= "192.168.2.9";
3537 0   0     0 $user ||= "qmaill";
3538 0         0 my $qmdir = $self->qmail->get_qmail_dir;
3539 0         0 my $supervise = $self->qmail->get_supervise_dir;
3540 0   0     0 $log ||= "/var/log/mail";
3541              
3542 0         0 my $run_f = "$supervise/$serv/log/run";
3543              
3544 0 0       0 if ( -s $run_f ) {
3545 0         0 print "socklog_qmail_control skipping: $run_f exists!\n";
3546 0         0 return 1;
3547             }
3548              
3549 0         0 print "socklog_qmail_control creating: $run_f...";
3550 0         0 my @socklog_run_file = <<EO_SOCKLOG;
3551             #!/bin/sh
3552             LOGDIR=$log
3553             LOGSERVERIP=$ip
3554             PORT=10116
3555              
3556             PATH=$qmdir/bin:/usr/local/bin:/usr/bin:/bin
3557             export PATH
3558              
3559             exec setuidgid $user multilog t s4096 n20 \
3560             !"tryto -pv tcpclient -v \$LOGSERVERIP \$PORT sh -c 'cat >&7'" \
3561             \${LOGDIR}/$serv
3562             EO_SOCKLOG
3563 0         0 $self->util->file_write( $run_f, lines => \@socklog_run_file, mode => '0755' );
3564 0         0 print "done.\n";
3565             }
3566              
3567             sub spamassassin {
3568 3     3 0 13 my $self = shift;
3569 3         7 my %p = validate( @_, { $self->get_std_opts },);
3570              
3571 3 100       34 return $p{test_ok} if defined $p{test_ok};
3572              
3573 1 50       2 if ( !$self->conf->{install_spamassassin} ) {
3574 1         2 $self->audit( "spamassassin: installing, skipping (disabled)" );
3575 1         3 return;
3576             }
3577              
3578 0 0       0 if ( $OSNAME eq "freebsd" ) {
    0          
3579 0         0 $self->spamassassin_freebsd();
3580             }
3581             elsif ( $OSNAME eq "darwin" ) {
3582             $self->darwin->install_port( "procmail" )
3583 0 0       0 if $self->conf->{install_procmail};
3584 0         0 $self->darwin->install_port( "unzip" );
3585 0         0 $self->darwin->install_port( "p5-mail-audit" );
3586 0         0 $self->darwin->install_port( "p5-mail-spamassassin" );
3587 0 0       0 $self->darwin->install_port( "bogofilter" ) if $self->conf->{install_bogofilter};
3588             }
3589              
3590 0         0 $self->util->install_module( "Time::HiRes" );
3591 0         0 $self->util->install_module( "Mail::Audit" );
3592 0         0 $self->util->install_module( "HTML::Parser" );
3593 0         0 $self->util->install_module( "Archive::Tar" );
3594 0         0 $self->util->install_module( "NetAddr::IP" );
3595 0         0 $self->util->install_module( "LWP::UserAgent" ); # used by sa-update
3596 0         0 $self->util->install_module( "Mail::SpamAssassin" );
3597 0         0 $self->maildrop->install;
3598              
3599 0         0 $self->spamassassin_sql();
3600             }
3601              
3602             sub spamassassin_freebsd {
3603 0     0 0 0 my $self = shift;
3604              
3605 0         0 my $mysql = "WITHOUT_MYSQL=true";
3606 0 0       0 if ( $self->conf->{install_spamassassin_sql} ) {
3607 0         0 $mysql = "WITH_MYSQL=true";
3608             };
3609              
3610 0         0 $self->freebsd->install_port( "p5-Mail-SPF",
3611             options => "# Options for p5-Mail-SPF-2.007_3
3612             _OPTIONS_READ=p5-Mail-SPF-2.007_3
3613             _FILE_COMPLETE_OPTIONS_LIST=DOCS
3614             OPTIONS_FILE_UNSET+=DOCS
3615             ",
3616             );
3617 0         0 $self->freebsd->install_port( "spamassassin",
3618             category => 'mail',
3619             flags => "WITHOUT_SSL=1 BATCH=yes",
3620             options => "# This file is generated by Mail::Toaster
3621             # Options for spamassassin-3.2.5_2
3622             _OPTIONS_READ=spamassassin-3.2.5_2
3623             WITH_AS_ROOT=true
3624             WITH_SPAMC=true
3625             WITHOUT_SACOMPILE=true
3626             WITH_DKIM=true
3627             WITHOUT_SSL=true
3628             WITH_GNUPG=true
3629             $mysql
3630             WITHOUT_PGSQL=true
3631             WITH_RAZOR=true
3632             WITH_SPF_QUERY=true
3633             WITH_RELAY_COUNTRY=true",
3634             verbose => 0,
3635             );
3636              
3637             # the very old port didn't install a spamd.sh file
3638             # new versions install sa-spamd and require the rc.conf flag
3639 0 0       0 my $start = -f "/usr/local/etc/rc.d/spamd.sh" ? "/usr/local/etc/rc.d/spamd.sh"
    0          
3640             : -f "/usr/local/etc/rc.d/spamd" ? "/usr/local/etc/rc.d/spamd"
3641             : "/usr/local/etc/rc.d/sa-spamd"; # current location, 9/23/06
3642              
3643 0         0 my $flags = $self->conf->{install_spamassassin_flags};
3644              
3645 0         0 $self->freebsd->conf_check(
3646             check => "spamd_enable",
3647             line => 'spamd_enable="YES"',
3648             verbose => 0,
3649             );
3650              
3651 0         0 $self->freebsd->conf_check(
3652             check => "spamd_flags",
3653             line => qq{spamd_flags="$flags"},
3654             verbose => 0,
3655             );
3656              
3657 0         0 $self->gnupg_install();
3658 0         0 $self->spamassassin_update();
3659              
3660 0 0       0 unless ( $self->util->is_process_running("spamd") ) {
3661 0 0       0 if ( -x $start ) {
3662 0         0 print "Starting SpamAssassin...";
3663 0         0 $self->util->syscmd( "$start restart", verbose=>0 );
3664 0         0 print "done.\n";
3665             }
3666 0         0 else { print "WARN: couldn't start SpamAssassin's spamd.\n"; }
3667             }
3668             };
3669              
3670             sub spamassassin_sql {
3671              
3672             # set up the mysql database for use with SpamAssassin
3673             # http://svn.apache.org/repos/asf/spamassassin/branches/3.0/sql/README
3674              
3675 0     0 0 0 my $self = shift;
3676 0         0 my %p = validate( @_, { $self->get_std_opts },);
3677              
3678 0 0       0 return $p{test_ok} if defined $p{test_ok}; # for testing
3679              
3680 0 0 0     0 if ( ! $self->conf->{install_mysql} || ! $self->conf->{install_spamassassin_sql} ) {
3681 0         0 print "SpamAssasin MySQL integration not selected. skipping.\n";
3682 0         0 return 0;
3683             }
3684              
3685 0 0       0 if ( $OSNAME eq "freebsd" ) {
3686 0         0 $self->spamassassin_sql_freebsd();
3687             }
3688             else {
3689 0         0 $self->spamassassin_sql_manual();
3690             };
3691             };
3692              
3693             sub spamassassin_sql_manual {
3694 0     0 0 0 my $self = shift;
3695              
3696 0         0 print
3697             "Sorry, automatic MySQL SpamAssassin setup is not available on $OSNAME yet. You must
3698             do this process manually by locating the *_mysql.sql files that arrived with SpamAssassin. Run
3699             each one like this:
3700             mysql spamassassin < awl_mysql.sql
3701             mysql spamassassin < bayes_mysql.sql
3702             mysql spamassassin < userpref_mysql.sql
3703              
3704             Then configure SpamAssassin to use them by creating a sql.cf file in SpamAssassin's etc dir with
3705             the following contents:
3706              
3707             user_scores_dsn DBI:mysql:spamassassin:localhost
3708             user_scores_sql_username $self->conf->{install_spamassassin_dbuser}
3709             user_scores_sql_password $self->conf->{install_spamassassin_dbpass}
3710              
3711             # default query
3712             #SELECT preference, value FROM _TABLE_ WHERE username = _USERNAME_ OR username = '\@GLOBAL' ORDER BY username ASC
3713             # global, then domain level
3714             #SELECT preference, value FROM _TABLE_ WHERE username = _USERNAME_ OR username = '\@GLOBAL' OR username = '@~'||_DOMAIN_ ORDER BY username ASC
3715             # global overrides user prefs
3716             #SELECT preference, value FROM _TABLE_ WHERE username = _USERNAME_ OR username = '\@GLOBAL' ORDER BY username DESC
3717             # from the SA SQL README
3718             #user_scores_sql_custom_query SELECT preference, value FROM _TABLE_ WHERE username = _USERNAME_ OR username = '\$GLOBAL' OR username = CONCAT('%',_DOMAIN_) ORDER BY username ASC
3719              
3720             bayes_store_module Mail::SpamAssassin::BayesStore::SQL
3721             bayes_sql_dsn DBI:mysql:spamassassin:localhost
3722             bayes_sql_username $self->conf->{install_spamassassin_dbuser}
3723             bayes_sql_password $self->conf->{install_spamassassin_dbpass}
3724             #bayes_sql_override_username someusername
3725              
3726             auto_whitelist_factory Mail::SpamAssassin::SQLBasedAddrList
3727             user_awl_dsn DBI:mysql:spamassassin:localhost
3728             user_awl_sql_username $self->conf->{install_spamassassin_dbuser}
3729             user_awl_sql_password $self->conf->{install_spamassassin_dbpass}
3730             user_awl_sql_table awl
3731             ";
3732             };
3733              
3734             sub spamassassin_sql_freebsd {
3735 0     0 0 0 my $self = shift;
3736              
3737             # is SpamAssassin installed?
3738 0 0       0 if ( ! $self->freebsd->is_port_installed( "spamassassin" ) ) {
3739 0         0 print "SpamAssassin is not installed, skipping database setup.\n";
3740 0         0 return;
3741             }
3742              
3743             # have we been here already?
3744 0 0       0 if ( -f "/usr/local/etc/mail/spamassassin/sql.cf" ) {
3745 0         0 print "SpamAssassin database setup already done...skipping.\n";
3746 0         0 return 1;
3747             };
3748              
3749 0         0 print "SpamAssassin is installed, setting up MySQL databases\n";
3750              
3751 0         0 my $user = $self->conf->{install_spamassassin_dbuser};
3752 0         0 my $pass = $self->conf->{install_spamassassin_dbpass};
3753              
3754 0         0 my $dot = $self->mysql->parse_dot_file( ".my.cnf", "[mysql]", 0 );
3755 0         0 my ( $dbh, $dsn, $drh ) = $self->mysql->connect( $dot, 1 );
3756              
3757 0 0       0 if ($dbh) {
3758 0         0 my $query = "use spamassassin";
3759 0         0 my $sth = $self->mysql->query( $dbh, $query, 1 );
3760 0 0       0 if ( $sth->errstr ) {
3761 0         0 print "oops, no spamassassin database.\n";
3762 0         0 print "creating MySQL spamassassin database.\n";
3763 0         0 $query = "CREATE DATABASE spamassassin";
3764 0         0 $sth = $self->mysql->query( $dbh, $query );
3765 0         0 $query =
3766             "GRANT ALL PRIVILEGES ON spamassassin.* TO $user\@'localhost' IDENTIFIED BY '$pass'";
3767 0         0 $sth = $self->mysql->query( $dbh, $query );
3768 0         0 $sth = $self->mysql->query( $dbh, "flush privileges" );
3769 0         0 $sth->finish;
3770             }
3771             else {
3772 0         0 print "spamassassin: spamassassin database exists!\n";
3773 0         0 $sth->finish;
3774             }
3775             }
3776              
3777 0         0 my $mysqlbin = $self->util->find_bin( 'mysql', fatal => 0 );
3778 0 0       0 if ( ! -x $mysqlbin ) {
3779 0         0 $mysqlbin = $self->util->find_bin( 'mysql5' );
3780             };
3781 0         0 my $sqldir = "/usr/local/share/doc/spamassassin/sql";
3782 0         0 foreach my $f (qw/bayes_mysql.sql awl_mysql.sql userpref_mysql.sql/) {
3783 0 0       0 if ( ! -f "$sqldir/$f" ) {
3784 0         0 warn "missing .sql file: $f\n";
3785 0         0 next;
3786             };
3787 0 0       0 if ( `grep MyISAM "$sqldir/$f"` ) {
3788 0         0 my @lines = $self->util->file_read( "$sqldir/$f" );
3789 0         0 foreach my $line (@lines) {
3790 0 0       0 if ( $line eq ') TYPE=MyISAM;' ) {
3791 0         0 $line = ');';
3792             };
3793             };
3794 0         0 $self->util->file_write( "$sqldir/$f", lines=>\@lines );
3795             };
3796 0         0 $self->util->syscmd( "$mysqlbin spamassassin < $sqldir/$f" );
3797             }
3798              
3799 0         0 my $file = "/usr/local/etc/mail/spamassassin/sql.cf";
3800 0 0       0 unless ( -f $file ) {
3801 0         0 my @lines = <<EO_SQL_CF;
3802             loadplugin Mail::SpamAssassin::Plugin::AWL
3803              
3804             user_scores_dsn DBI:mysql:spamassassin:localhost
3805             user_scores_sql_username $self->conf->{install_spamassassin_dbuser}
3806             user_scores_sql_password $self->conf->{install_spamassassin_dbpass}
3807             #user_scores_sql_table userpref
3808              
3809             bayes_store_module Mail::SpamAssassin::BayesStore::SQL
3810             bayes_sql_dsn DBI:mysql:spamassassin:localhost
3811             bayes_sql_username $self->conf->{install_spamassassin_dbuser}
3812             bayes_sql_password $self->conf->{install_spamassassin_dbpass}
3813             #bayes_sql_override_username someusername
3814              
3815             auto_whitelist_factory Mail::SpamAssassin::SQLBasedAddrList
3816             user_awl_dsn DBI:mysql:spamassassin:localhost
3817             user_awl_sql_username $self->conf->{install_spamassassin_dbuser}
3818             user_awl_sql_password $self->conf->{install_spamassassin_dbpass}
3819             user_awl_sql_table awl
3820             EO_SQL_CF
3821 0         0 $self->util->file_write( $file, lines => \@lines );
3822             }
3823             }
3824              
3825             sub spamassassin_update {
3826 0     0 0 0 my $self = shift;
3827              
3828 0 0       0 my $update = $self->util->find_bin( "sa-update", fatal => 0 ) or return;
3829 0 0       0 system $update and do {
3830 0         0 $self->error( "error updating spamassassin rules", fatal => 0);
3831             };
3832 0         0 $self->audit( "trying again without GPG" );
3833              
3834 0 0       0 system "$update --nogpg" and
3835             return $self->error( "error updating spamassassin rules", fatal => 0);
3836              
3837 0         0 return 1;
3838             };
3839              
3840             sub sqlite_freebsd {
3841 0     0 0 0 my $self = shift;
3842              
3843 0         0 $self->freebsd->install_port( 'icu',
3844             options => "# Options for icu-50.1.2
3845             _OPTIONS_READ=icu-50.1.2
3846             _FILE_COMPLETE_OPTIONS_LIST=THREADS
3847             OPTIONS_FILE_SET+=THREADS
3848             ",
3849             );
3850              
3851 0         0 $self->freebsd->install_port( 'sqlite3',
3852             options => "
3853             # Options for sqlite3-3.7.17_1
3854             _OPTIONS_READ=sqlite3-3.7.17_1
3855             _FILE_COMPLETE_OPTIONS_LIST=DIRECT_READ EXTENSION FTS3 ICU MEMMAN METADATA RAMTABLE RTREE SECURE_DELETE SOUNDEX STAT3 THREADSAFE UNLOCK_NOTIFY UPD_DEL_LIMIT URI
3856             OPTIONS_FILE_UNSET+=DIRECT_READ
3857             OPTIONS_FILE_SET+=EXTENSION
3858             OPTIONS_FILE_SET+=FTS3
3859             OPTIONS_FILE_SET+=ICU
3860             OPTIONS_FILE_UNSET+=MEMMAN
3861             OPTIONS_FILE_SET+=METADATA
3862             OPTIONS_FILE_UNSET+=RAMTABLE
3863             OPTIONS_FILE_UNSET+=RTREE
3864             OPTIONS_FILE_SET+=SECURE_DELETE
3865             OPTIONS_FILE_UNSET+=SOUNDEX
3866             OPTIONS_FILE_UNSET+=STAT3
3867             OPTIONS_FILE_SET+=THREADSAFE
3868             OPTIONS_FILE_SET+=UNLOCK_NOTIFY
3869             OPTIONS_FILE_UNSET+=UPD_DEL_LIMIT
3870             OPTIONS_FILE_SET+=URI
3871             ",
3872             );
3873             }
3874              
3875             sub squirrelmail {
3876 3     3 0 12 my $self = shift;
3877 3         7 my %p = validate( @_, { $self->get_std_opts },);
3878              
3879 3 100       15 return $p{test_ok} if defined $p{test_ok}; # for testing
3880              
3881 1 50       2 my $ver = $self->conf->{install_squirrelmail} or do {
3882 1         2 $self->audit( 'skipping squirrelmail install (disabled)');
3883 1         3 return;
3884             };
3885              
3886 0 0 0     0 if ( $OSNAME eq "freebsd" && $ver eq "port" ) {
3887 0         0 $self->php();
3888 0 0       0 $self->squirrelmail_freebsd() and return;
3889             };
3890              
3891 0 0       0 $ver = "1.4.6" if $ver eq 'port';
3892              
3893 0         0 print "squirrelmail: attempting to install from sources.\n";
3894              
3895 0   0     0 my $htdocs = $self->conf->{toaster_http_docs} || "/usr/local/www/data";
3896 0   0     0 my $srcdir = $self->conf->{toaster_src_dir} || "/usr/local/src";
3897 0         0 $srcdir .= "/mail";
3898              
3899 0 0       0 unless ( -d $htdocs ) {
3900 0 0       0 $htdocs = "/var/www/data" if ( -d "/var/www/data" ); # linux
3901 0 0       0 $htdocs = "/Library/Webserver/Documents"
3902             if ( -d "/Library/Webserver/Documents" ); # OS X
3903             }
3904              
3905 0 0       0 if ( -d "$htdocs/squirrelmail" ) {
3906 0         0 print "Squirrelmail is already installed, I won't install it again!\n";
3907 0         0 return 0;
3908             }
3909              
3910             $self->util->install_from_source(
3911             package => "squirrelmail-$ver",
3912             site => "http://" . $self->conf->{toaster_sf_mirror},
3913 0         0 url => "/squirrelmail",
3914             targets => ["mv $srcdir/squirrelmail-$ver $htdocs/squirrelmail"],
3915             source_sub_dir => 'mail',
3916             );
3917              
3918 0         0 $self->squirrelmail_config();
3919 0         0 $self->squirrelmail_mysql();
3920             }
3921              
3922             sub squirrelmail_freebsd {
3923 0     0 0 0 my $self = shift;
3924              
3925 0         0 my @squirrel_flags;
3926 0 0       0 push @squirrel_flags, 'WITH_DATABASE=1' if $self->conf->{install_squirrelmail_sql};
3927              
3928 0         0 $self->freebsd->install_port( "squirrelmail",
3929             flags => join(',', @squirrel_flags),
3930             );
3931 0         0 $self->freebsd->install_port( "squirrelmail-quota_usage-plugin" );
3932              
3933 0 0       0 return if ! $self->freebsd->is_port_installed( "squirrelmail" );
3934 0         0 my $sqdir = "/usr/local/www/squirrelmail";
3935 0 0       0 return if ! -d $sqdir;
3936              
3937 0         0 $self->squirrelmail_config();
3938 0         0 $self->squirrelmail_mysql();
3939              
3940 0         0 return 1;
3941             }
3942              
3943             sub squirrelmail_mysql {
3944 0     0 0 0 my $self = shift;
3945              
3946 0 0       0 return if ! $self->conf->{install_mysql};
3947 0 0       0 return if ! $self->conf->{install_squirrelmail_sql};
3948              
3949 0 0       0 if ( $OSNAME eq "freebsd" ) {
3950 0         0 $self->freebsd->install_port( "pear-DB" );
3951              
3952 0         0 print
3953             '\nHEY! You need to add include_path = ".:/usr/local/share/pear" to php.ini.\n\n';
3954              
3955 0         0 $self->freebsd->install_port( "php5-mysql" );
3956 0         0 $self->freebsd->install_port( "squirrelmail-sasql-plugin" );
3957             }
3958              
3959 0         0 my $db = "squirrelmail";
3960 0         0 my $user = "squirrel";
3961 0   0     0 my $pass = $self->conf->{install_squirrelmail_sql_pass} || "secret";
3962 0         0 my $host = "localhost";
3963              
3964 0         0 my $dot = $self->mysql->parse_dot_file( ".my.cnf", "[mysql]", 0 );
3965 0         0 my ( $dbh, $dsn, $drh ) = $self->mysql->connect( $dot, 1 );
3966              
3967 0 0       0 if ($dbh) {
3968 0         0 my $query = "use squirrelmail";
3969 0         0 my $sth = $self->mysql->query( $dbh, $query, 1 );
3970              
3971 0 0       0 if ( !$sth->errstr ) {
3972 0         0 print "squirrelmail: squirrelmail database already exists.\n";
3973 0         0 $sth->finish;
3974 0         0 return 1;
3975             }
3976              
3977 0         0 print "squirrelmail: creating MySQL database for squirrelmail.\n";
3978 0         0 $query = "CREATE DATABASE squirrelmail";
3979 0         0 $sth = $self->mysql->query( $dbh, $query );
3980              
3981 0         0 $query =
3982             "GRANT ALL PRIVILEGES ON $db.* TO $user\@'$host' IDENTIFIED BY '$pass'";
3983 0         0 $sth = $self->mysql->query( $dbh, $query );
3984              
3985 0         0 $query =
3986             "CREATE TABLE squirrelmail.address ( owner varchar(128) DEFAULT '' NOT NULL,
3987             nickname varchar(16) DEFAULT '' NOT NULL, firstname varchar(128) DEFAULT '' NOT NULL,
3988             lastname varchar(128) DEFAULT '' NOT NULL, email varchar(128) DEFAULT '' NOT NULL,
3989             label varchar(255), PRIMARY KEY (owner,nickname), KEY firstname (firstname,lastname));
3990             ";
3991 0         0 $sth = $self->mysql->query( $dbh, $query );
3992              
3993 0         0 $query =
3994             "CREATE TABLE squirrelmail.global_abook ( owner varchar(128) DEFAULT '' NOT NULL, nickname varchar(16) DEFAULT '' NOT NULL, firstname varchar(128) DEFAULT '' NOT NULL,
3995             lastname varchar(128) DEFAULT '' NOT NULL, email varchar(128) DEFAULT '' NOT NULL,
3996             label varchar(255), PRIMARY KEY (owner,nickname), KEY firstname (firstname,lastname));";
3997              
3998 0         0 $sth = $self->mysql->query( $dbh, $query );
3999              
4000 0         0 $query =
4001             "CREATE TABLE squirrelmail.userprefs ( user varchar(128) DEFAULT '' NOT NULL, prefkey varchar(64) DEFAULT '' NOT NULL, prefval BLOB DEFAULT '' NOT NULL, PRIMARY KEY (user,prefkey))";
4002 0         0 $sth = $self->mysql->query( $dbh, $query );
4003              
4004 0         0 $sth->finish;
4005 0         0 return 1;
4006             }
4007              
4008 0         0 print "
4009              
4010             WARNING: I could not connect to your database server! If this is a new install,
4011             you will need to connect to your database server and run this command manually:
4012              
4013             mysql -u root -h $host -p
4014             CREATE DATABASE squirrelmail;
4015             GRANT ALL PRIVILEGES ON $db.* TO $user\@'$host' IDENTIFIED BY '$pass';
4016             CREATE TABLE squirrelmail.address (
4017             owner varchar(128) DEFAULT '' NOT NULL,
4018             nickname varchar(16) DEFAULT '' NOT NULL,
4019             firstname varchar(128) DEFAULT '' NOT NULL,
4020             lastname varchar(128) DEFAULT '' NOT NULL,
4021             email varchar(128) DEFAULT '' NOT NULL,
4022             label varchar(255),
4023             PRIMARY KEY (owner,nickname),
4024             KEY firstname (firstname,lastname)
4025             );
4026             CREATE TABLE squirrelmail.global_abook (
4027             owner varchar(128) DEFAULT '' NOT NULL,
4028             nickname varchar(16) DEFAULT '' NOT NULL,
4029             firstname varchar(128) DEFAULT '' NOT NULL,
4030             lastname varchar(128) DEFAULT '' NOT NULL,
4031             email varchar(128) DEFAULT '' NOT NULL,
4032             label varchar(255),
4033             PRIMARY KEY (owner,nickname),
4034             KEY firstname (firstname,lastname)
4035             );
4036             CREATE TABLE squirrelmail.userprefs (
4037             user varchar(128) DEFAULT '' NOT NULL,
4038             prefkey varchar(64) DEFAULT '' NOT NULL,
4039             prefval BLOB DEFAULT '' NOT NULL,
4040             PRIMARY KEY (user,prefkey)
4041             );
4042             quit;
4043              
4044             If this is an upgrade, you can probably ignore this warning.
4045              
4046             ";
4047             }
4048              
4049             sub squirrelmail_config {
4050 0     0 0 0 my $self = shift;
4051              
4052 0         0 my $sqdir = "/usr/local/www/squirrelmail";
4053 0 0       0 return 1 if -e "$sqdir/config/config.php";
4054              
4055 0         0 chdir("$sqdir/config");
4056 0         0 print "squirrelmail: installing a default config.php\n";
4057              
4058 0         0 copy('config_default.php', 'config.php');
4059              
4060 0         0 my $mailhost = $self->conf->{toaster_hostname};
4061 0         0 my $dsn = '';
4062              
4063 0 0       0 if ( $self->conf->{install_squirrelmail_sql} ) {
4064 0   0     0 my $pass = $self->conf->{install_squirrelmail_sql_pass} || 's3kret';
4065 0         0 $dsn = "mysql://squirrel:$pass\@localhost/squirrelmail";
4066             }
4067              
4068 0         0 my $string = <<"EOCONFIG";
4069             <?php
4070             \$signout_page = 'https://$mailhost/';
4071             \$provider_name = 'Powered by Mail::Toaster';
4072             \$provider_uri = 'http://www.tnpi.net/wiki/Mail_Toaster';
4073             \$domain = '$mailhost';
4074             \$useSendmail = true;
4075             \$imap_server_type = 'dovecot';
4076             \$addrbook_dsn = '$dsn';
4077             \$prefs_dsn = '$dsn';
4078             ?>
4079             EOCONFIG
4080             ;
4081              
4082 0         0 $self->util->file_write( "config_local.php", lines => [ $string ] );
4083              
4084 0 0       0 if ( -d "$sqdir/plugins/sasql" ) {
4085 0 0       0 if ( ! -e "$sqdir/plugins/sasql/sasql_conf.php" ) {
4086 0         0 copy('sasql_conf.php.dist', 'sasql_conf.php');
4087             };
4088              
4089 0         0 my $user = $self->conf->{install_spamassassin_dbuser};
4090 0         0 my $pass = $self->conf->{install_spamassassin_dbpass};
4091 0         0 $self->config->apply_tweaks(
4092             file => "$sqdir/plugins/sasql/sasql_conf.php",
4093             changes => [
4094             { search => q{$SqlDSN = 'mysql://<user>:<pass>@<host>/<db>';},
4095             replace => "\$SqlDSN = 'mysql://$user:$pass\@localhost/spamassassin'",
4096             },
4097             ],
4098             );
4099             };
4100             }
4101              
4102             sub sqwebmail {
4103 3     3 0 11 my $self = shift;
4104 3         8 my %p = validate( @_, { $self->get_std_opts },);
4105              
4106 3 100       16 return $p{test_ok} if defined $p{test_ok};
4107              
4108 1 50       3 my $ver = $self->conf->{install_sqwebmail} or do {
4109 1         2 $self->audit( 'skipping sqwebmail install (disabled)');
4110 1         3 return;
4111             };
4112              
4113 0   0     0 my $httpdir = $self->conf->{toaster_http_base} || "/usr/local/www";
4114 0         0 my $cgi = $self->conf->{toaster_cgi_bin};
4115 0   0     0 my $prefix = $self->conf->{toaster_prefix} || "/usr/local";
4116              
4117 0 0 0     0 unless ( $cgi && -d $cgi ) { $cgi = "$httpdir/cgi-bin" }
  0         0  
4118              
4119 0         0 my $datadir = $self->conf->{toaster_http_docs};
4120 0 0       0 unless ( -d $datadir ) {
4121 0 0       0 if ( -d "$httpdir/data/mail" ) { $datadir = "$httpdir/data/mail"; }
  0 0       0  
4122 0         0 elsif ( -d "$httpdir/mail" ) { $datadir = "$httpdir/mail"; }
4123 0         0 else { $datadir = "$httpdir/data"; }
4124             }
4125              
4126 0 0       0 my $mime = -e "$prefix/etc/apache2/mime.types" ? "$prefix/etc/apache2/mime.types"
    0          
    0          
4127             : -e "$prefix/etc/apache22/mime.types" ? "$prefix/etc/apache22/mime.types"
4128             : -e "$prefix/etc/apache24/mime.types" ? "$prefix/etc/apache24/mime.types"
4129             : "$prefix/etc/apache/mime.types";
4130              
4131 0         0 my $cachedir = "/var/run/sqwebmail";
4132              
4133 0 0 0     0 if ( $OSNAME eq "freebsd" && $ver eq "port" ) {
4134 0         0 return $self->sqwebmail_freebsd_port();
4135             };
4136              
4137 0 0       0 $ver = "5.3.1" if $ver eq "port";
4138              
4139 0 0       0 if ( -x "$prefix/libexec/sqwebmail/sqwebmaild" ) {
4140 0 0       0 if ( !$self->util->yes_or_no(
4141             "Sqwebmail is already installed, re-install it?",
4142             timeout => 300
4143             )
4144             )
4145             {
4146 0         0 print "ok, skipping.\n";
4147 0         0 return;
4148             }
4149             }
4150              
4151 0         0 my $package = "sqwebmail-$ver";
4152 0         0 my $site = "http://" . $self->conf->{toaster_sf_mirror} . "/courier";
4153 0   0     0 my $src = $self->conf->{toaster_src_dir} || "/usr/local/src";
4154              
4155 0         0 $self->util->cwd_source_dir( "$src/mail" );
4156              
4157 0 0       0 if ( -d "$package" ) {
4158 0 0       0 unless ( $self->util->source_warning( $package, 1, $src ) ) {
4159 0         0 carp "sqwebmail: OK, skipping sqwebmail.\n";
4160 0         0 return;
4161             }
4162             }
4163              
4164 0 0       0 unless ( -e "$package.tar.bz2" ) {
4165 0         0 $self->util->get_url( "$site/$package.tar.bz2" );
4166 0 0       0 unless ( -e "$package.tar.bz2" ) {
4167 0         0 croak "sqwebmail FAILED: coudn't fetch $package\n";
4168             }
4169             }
4170              
4171 0         0 $self->util->extract_archive( "$package.tar.bz2" );
4172              
4173 0 0       0 chdir($package) or croak "sqwebmail FAILED: coudn't chdir $package\n";
4174              
4175 0         0 my $cmd = "./configure --prefix=$prefix --with-htmldir=$prefix/share/sqwebmail "
4176             . "--with-cachedir=/var/run/sqwebmail --enable-webpass=vpopmail "
4177             . "--with-module=authvchkpw --enable-https --enable-logincache "
4178             . "--enable-imagedir=$datadir/webmail --without-authdaemon "
4179             . "--enable-mimetypes=$mime --enable-cgibindir=" . $cgi;
4180              
4181 0 0       0 if ( $OSNAME eq "darwin" ) { $cmd .= " --with-cacheowner=daemon"; };
  0         0  
4182              
4183 0         0 my $make = $self->util->find_bin("gmake", fatal=>0, verbose=>0);
4184 0   0     0 $make ||= $self->util->find_bin("make", fatal=>0, verbose=>0);
4185              
4186 0         0 $self->util->syscmd( $cmd );
4187 0         0 $self->util->syscmd( "$make configure-check" );
4188 0         0 $self->util->syscmd( "$make check" );
4189 0         0 $self->util->syscmd( "$make" );
4190              
4191 0         0 my $share = "$prefix/share/sqwebmail";
4192 0 0       0 if ( -d $share ) {
4193 0         0 $self->util->syscmd( "make install-exec" );
4194 0         0 print
4195             "\n\nWARNING: I have only installed the $package binaries, thus\n";
4196 0         0 print "preserving any custom settings you might have in $share.\n";
4197 0         0 print
4198             "If you wish to do a full install, overwriting any customizations\n";
4199 0         0 print "you might have, then do this:\n\n";
4200 0         0 print "\tcd $src/mail/$package; make install\n";
4201             }
4202             else {
4203 0         0 $self->util->syscmd( "$make install" );
4204 0         0 chmod oct('0755'), $share;
4205 0         0 chmod oct('0755'), "$datadir/sqwebmail";
4206 0 0       0 copy( "$share/ldapaddressbook.dist", "$share/ldapaddressbook" )
4207             or croak "copy failed: $!";
4208             }
4209              
4210 0         0 $self->util->syscmd( "$make install-configure", fatal => 0 );
4211 0         0 $self->sqwebmail_conf();
4212             }
4213              
4214             sub sqwebmail_conf {
4215 0     0 0 0 my $self = shift;
4216 0         0 my %p = validate(@_, { $self->get_std_opts },);
4217              
4218 0         0 my $cachedir = "/var/run/sqwebmail";
4219 0   0     0 my $prefix = $self->conf->{toaster_prefix} || "/usr/local";
4220              
4221 0 0       0 unless ( -e $cachedir ) {
4222 0         0 my $uid = getpwnam("bin");
4223 0         0 my $gid = getgrnam("bin");
4224 0         0 mkdir( $cachedir, oct('0755') );
4225 0         0 chown( $uid, $gid, $cachedir );
4226             }
4227              
4228 0         0 my $file = "/usr/local/etc/sqwebmail/sqwebmaild";
4229 0 0       0 return if ! -w $file;
4230              
4231 0         0 my @lines = $self->util->file_read( $file );
4232 0         0 foreach my $line (@lines) { #
4233 0 0       0 if ( $line =~ /^[#]{0,1}PIDFILE/ ) {
4234 0         0 $line = "PIDFILE=$cachedir/sqwebmaild.pid";
4235             };
4236             };
4237 0         0 $self->util->file_write( $file, lines=>\@lines );
4238             }
4239              
4240             sub sqwebmail_freebsd_port {
4241 0     0 0 0 my $self = shift;
4242              
4243 0         0 $self->gnupg_install;
4244 0         0 $self->courier_authlib;
4245              
4246 0         0 my $cgi = $self->conf->{toaster_cgi_bin};
4247 0         0 my $datadir = $self->conf->{toaster_http_docs};
4248 0         0 my $cachedir = "/var/run/sqwebmail";
4249              
4250 0 0       0 if ( $cgi =~ /\/usr\/local\/(.*)$/ ) { $cgi = $1; }
  0         0  
4251 0 0       0 if ( $datadir =~ /\/usr\/local\/(.*)$/ ) { $datadir = $1; }
  0         0  
4252              
4253 0         0 my @args = "CGIBINDIR=$cgi";
4254 0         0 push @args, "CGIBINSUBDIR=''";
4255 0         0 push @args, "WEBDATADIR=$datadir";
4256 0         0 push @args, "CACHEDIR=$cachedir";
4257              
4258 0         0 $self->freebsd->install_port( "sqwebmail",
4259             flags => join( ",", @args ),
4260             options => "# Options for sqwebmail-5.6.1
4261             _OPTIONS_READ=sqwebmail-5.6.1
4262             _FILE_COMPLETE_OPTIONS_LIST=AUTH_LDAP AUTH_MYSQL AUTH_PGSQL AUTH_USERDB AUTH_VCHKPW CACHEDIR CHARSET FAM GDBM GZIP HTTPS HTTPS_LOGIN ISPELL MIMETYPES SENTRENAME
4263             OPTIONS_FILE_UNSET+=AUTH_LDAP
4264             OPTIONS_FILE_UNSET+=AUTH_MYSQL
4265             OPTIONS_FILE_UNSET+=AUTH_PGSQL
4266             OPTIONS_FILE_UNSET+=AUTH_USERDB
4267             OPTIONS_FILE_SET+=AUTH_VCHKPW
4268             OPTIONS_FILE_SET+=CACHEDIR
4269             OPTIONS_FILE_UNSET+=CHARSET
4270             OPTIONS_FILE_UNSET+=FAM
4271             OPTIONS_FILE_UNSET+=GDBM
4272             OPTIONS_FILE_SET+=GZIP
4273             OPTIONS_FILE_SET+=HTTPS
4274             OPTIONS_FILE_UNSET+=HTTPS_LOGIN
4275             OPTIONS_FILE_SET+=ISPELL
4276             OPTIONS_FILE_SET+=MIMETYPES
4277             OPTIONS_FILE_UNSET+=SENTRENAME
4278             ",
4279             );
4280              
4281 0         0 $self->freebsd->conf_check(
4282             check => "sqwebmaild_enable",
4283             line => 'sqwebmaild_enable="YES"',
4284             );
4285              
4286 0         0 $self->sqwebmail_conf();
4287              
4288 0         0 print "sqwebmail: starting sqwebmaild.\n";
4289 0   0     0 my $prefix = $self->conf->{toaster_prefix} || "/usr/local";
4290 0         0 my $start = "$prefix/etc/rc.d/sqwebmail-sqwebmaild";
4291              
4292 0 0       0 -x $start ? $self->util->syscmd( "$start start" )
    0          
4293             : -x "$start.sh" ? $self->util->syscmd( "$start.sh start" )
4294             : carp "could not find the startup file for sqwebmaild!\n";
4295              
4296 0         0 $self->freebsd->is_port_installed( "sqwebmail" );
4297             }
4298              
4299             sub stunnel {
4300 0     0 0 0 my $self = shift;
4301              
4302 0 0       0 return $self->stunnel_freebsd() if $OSNAME eq 'freebsd';
4303              
4304 0         0 my $stunnel = $self->util->find_bin('stunnel', fatal=>0);
4305              
4306 0 0       0 $self->error("stunnel is not installed and you selected pop3_ssl_daemon eq 'qpop3d'. Either install stunnel or change your configuration settings." ) if ! -x $stunnel;
4307 0         0 return;
4308             };
4309              
4310             sub stunnel_freebsd {
4311 0     0 0 0 my $self = shift;
4312 0         0 return $self->freebsd->install_port( "stunnel",
4313             options => "#
4314             # This file was generated by mail-toaster\n
4315             # Options for stunnel-4.33
4316             _OPTIONS_READ=stunnel-4.33
4317             WITHOUT_FORK=true
4318             WITH_PTHREAD=true
4319             WITHOUT_UCONTEXT=true
4320             WITHOUT_DH=true
4321             WITHOUT_IPV6=true
4322             WITH_LIBWRAP=true\n",
4323             );
4324             };
4325              
4326             sub supervise {
4327 0     0 0 0 my $self = shift;
4328 0         0 my %p = validate( @_, { $self->get_std_opts } );
4329              
4330 0 0       0 return $p{test_ok} if defined $p{test_ok};
4331              
4332 0         0 $self->toaster->supervise_dirs_create(%p);
4333 0         0 $self->toaster->service_dir_create(%p);
4334              
4335 0         0 $self->qmail->control_create(%p);
4336 0         0 $self->qmail->install_qmail_control_files(%p);
4337 0         0 $self->qmail->install_qmail_control_log_files(%p);
4338              
4339 0         0 $self->startup_script();
4340 0         0 $self->toaster->service_symlinks();
4341 0         0 $self->qmail->config();
4342 0         0 $self->supervise_startup(%p);
4343             };
4344              
4345             sub supervise_startup {
4346 0     0 0 0 my $self = shift;
4347 0         0 my %p = validate( @_, { $self->get_std_opts } );
4348              
4349 0         0 my $svok = $self->util->find_bin( 'svok', verbose => 0);
4350 0   0     0 my $svc_dir = $self->conf->{qmail_service} || '/var/service';
4351 0 0       0 if ( (system "$svok $svc_dir/send") == 0 ) {
4352 0         0 $self->audit("supervised processes are already started");
4353 0         0 return;
4354             };
4355              
4356 0         0 my $start = $self->util->find_bin( 'services', verbose => 0);
4357 0         0 print "\n\nStarting up qmail services (Ctrl-C to cancel).
4358              
4359             If there's problems, you can stop all supervised services by running:\n
4360             $start stop\n
4361             \n\nStarting in 5 seconds: ";
4362 0         0 foreach ( 1 .. 5 ) { print '.'; sleep 1; };
  0         0  
  0         0  
4363 0         0 print "\n";
4364              
4365 0         0 system "$start start";
4366             }
4367              
4368             sub startup_script {
4369 0     0 1 0 my $self = shift;
4370 0         0 my %p = validate( @_, { $self->get_std_opts },);
4371              
4372 0   0     0 my $dl_site = $self->conf->{toaster_dl_site} || "http://www.tnpi.net";
4373 0         0 my $dl_url = "$dl_site/internet/mail/toaster";
4374              
4375             # make sure the service dir is set up
4376 0 0       0 return $self->error( "the service directories don't appear to be set up. I refuse to start them until this is fixed.") unless $self->toaster->service_dir_test();
4377              
4378 0 0       0 return $p{test_ok} if defined $p{test_ok};
4379              
4380 0 0       0 return $self->startup_script_freebsd() if $OSNAME eq 'freebsd';
4381 0 0       0 return $self->startup_script_darwin() if $OSNAME eq 'darwin';
4382              
4383 0         0 $self->error( "There is no startup script support written for $OSNAME. If you know the proper method of doing so, please have a look at $dl_url/start/services.txt, adapt it to $OSNAME, and send it to matt\@tnpi.net." );
4384             };
4385              
4386             sub startup_script_darwin {
4387 0     0 0 0 my $self = shift;
4388              
4389 0         0 my $start = "/Library/LaunchDaemons/to.yp.cr.daemontools-svscan.plist";
4390 0   0     0 my $dl_site = $self->conf->{toaster_dl_site} || "http://www.tnpi.net";
4391 0         0 my $dl_url = "$dl_site/internet/mail/toaster";
4392              
4393 0 0       0 unless ( -e $start ) {
4394 0         0 $self->util->get_url( "$dl_url/start/to.yp.cr.daemontools-svscan.plist" );
4395 0 0       0 my $r = $self->util->install_if_changed(
4396             newfile => "to.yp.cr.daemontools-svscan.plist",
4397             existing => $start,
4398             mode => '0551',
4399             clean => 1,
4400             ) or return;
4401 0 0       0 $r == 1 ? $r = "ok" : $r = "ok (current)";
4402 0         0 $self->audit( "startup_script: updating $start, $r" );
4403             }
4404              
4405 0   0     0 my $prefix = $self->conf->{toaster_prefix} || "/usr/local";
4406 0         0 $start = "$prefix/sbin/services";
4407              
4408 0 0       0 if ( -w $start ) {
4409 0         0 $self->util->get_url( "$dl_url/start/services-darwin.txt" );
4410              
4411 0 0       0 my $r = $self->util->install_if_changed(
4412             newfile => "services-darwin.txt",
4413             existing => $start,
4414             mode => '0551',
4415             clean => 1,
4416             ) or return;
4417              
4418 0 0       0 $r == 1 ? $r = "ok" : $r = "ok (current)";
4419              
4420 0         0 $self->audit( "startup_script: updating $start, $r" );
4421             }
4422             };
4423              
4424             sub startup_script_freebsd {
4425 0     0 0 0 my $self = shift;
4426              
4427             # The FreeBSD port for daemontools includes rc.d/svscan so we use it
4428 0   0     0 my $confdir = $self->conf->{system_config_dir} || "/usr/local/etc";
4429 0         0 my $start = "$confdir/rc.d/svscan";
4430              
4431 0 0       0 unless ( -f $start ) {
4432 0         0 print "WARNING: no svscan, is daemontools installed?\n";
4433 0         0 print "\n\nInstalling a generic startup file....";
4434              
4435 0   0     0 my $dl_site = $self->conf->{toaster_dl_site} || "http://www.tnpi.net";
4436 0         0 my $dl_url = "$dl_site/internet/mail/toaster";
4437 0         0 $self->util->get_url( "$dl_url/start/services.txt" );
4438 0 0       0 my $r = $self->util->install_if_changed(
4439             newfile => "services.txt",
4440             existing => $start,
4441             mode => '0751',
4442             clean => 1,
4443             ) or return;
4444              
4445 0 0       0 $r == 1 ? $r = "ok" : $r = "ok (current)";
4446              
4447 0         0 $self->audit( "startup_script: updating $start, $r" );
4448             }
4449              
4450             $self->freebsd->conf_check(
4451 0         0 check => "svscan_enable",
4452             line => 'svscan_enable="YES"',
4453             );
4454              
4455             # if the qmail start file is installed, nuke it
4456 0 0       0 unlink "$confdir/rc.d/qmail.sh" if -e "$confdir/rc.d/qmail";
4457 0 0       0 unlink "$confdir/rc.d/qmail.sh" if -e "$confdir/rc.d/qmail.sh";
4458              
4459 0   0     0 my $prefix = $self->conf->{toaster_prefix} || "/usr/local";
4460 0         0 my $sym = "$prefix/sbin/services";
4461 0 0 0     0 return 1 if ( -l $sym && -x $sym ); # already exists
4462              
4463 0 0 0     0 unlink $sym
4464             or return $self->error( "Please [re]move '$sym' and run again.",fatal=>0) if -e $sym;
4465              
4466 0         0 symlink( $start, $sym );
4467 0         0 $self->audit( "startup_script: added $sym as symlink to $start");
4468             };
4469              
4470             sub tcp_smtp {
4471 0     0 0 0 my $self = shift;
4472 0         0 my %p = validate( @_, { etc_dir => SCALAR } );
4473              
4474 0         0 my $etc_dir = $p{etc_dir};
4475              
4476             # test for an existing one
4477 0 0       0 if ( -s "$etc_dir/tcp.smtp" ) {
4478 0         0 my $count = $self->util->file_read( "$etc_dir/tcp.smtp" );
4479 0 0       0 if ( $count > 1 ) {
4480 0         0 return $self->audit("$etc_dir/tcp.smtp has customizations");
4481             };
4482 0         0 $self->util->archive_file( "$etc_dir/tcp.smtp" ); # back it up
4483             }
4484              
4485 0         0 my $qdir = $self->qmail->get_qmail_dir;
4486              
4487 0         0 my @lines = <<"EO_TCP_SMTP";
4488             # RELAYCLIENT="" means IP can relay
4489             # RBLSMTPD="" means DNSBLs are ignored for this IP
4490             # QMAILQUEUE="" is the qmail queue process, defaults to $qdir/bin/qmail-queue
4491             # CHKUSER_MBXQUOTA rejects messages when the users mailbox quota is filled
4492             #
4493             # common QMAILQUEUE settings:
4494             # QMAILQUEUE="$qdir/bin/qmail-queue"
4495             # QMAILQUEUE="$qdir/bin/simscan"
4496             #
4497             # handy test settings
4498             # 127.:allow,RELAYCLIENT="",RBLSMTPD="",QMAILQUEUE="$qdir/bin/simscan"
4499             # 127.:allow,RELAYCLIENT="",RBLSMTPD="",QMAILQUEUE="$qdir/bin/qscanq/bin/qscanq"
4500             127.0.0.1:allow,RELAYCLIENT="",RBLSMTPD=""
4501              
4502             #
4503             # Allow anyone with reverse DNS set up
4504             #=:allow
4505             # soft block on no reverse DNS
4506             #:allow,RBLSMTPD="Blocked - Reverse DNS queries for your IP fail. Fix your DNS!"
4507             # hard block on no reverse DNS
4508             #:allow,RBLSMTPD="-Blocked - Reverse DNS queries for your IP fail. You cannot send me mail."
4509             # default allow
4510             #:allow,QMAILQUEUE="$qdir/bin/simscan",CHKUSER_MBXQUOTA="99"
4511             :allow,CHKUSER_MBXQUOTA="99"
4512             EO_TCP_SMTP
4513             ;
4514 0         0 $self->util->file_write( "$etc_dir/tcp.smtp", lines => \@lines, mode => '0644' );
4515             }
4516              
4517             sub tcp_smtp_cdb {
4518 0     0 0 0 my $self = shift;
4519 0         0 my %p = validate( @_, { 'etc_dir' => SCALAR } );
4520 0         0 my $dir = $p{etc_dir};
4521              
4522 0         0 my $tcprules = $self->util->find_bin('tcprules');
4523 0 0       0 $self->util->syscmd( "$tcprules $dir/tcp.smtp.cdb $dir/tcp.smtp.tmp < $dir/tcp.smtp" )
4524             or return;
4525 0         0 chmod 0644, "$dir/tcp.smtp";
4526 0         0 chmod 0644, "$dir/tcp.smtp.cdb";
4527 0         0 print "Reloaded $dir/tcp.smtp";
4528 0         0 return 1;
4529             };
4530              
4531             sub test {
4532 0     0 1 0 require Mail::Toaster::Setup::Test;
4533 0         0 return Mail::Toaster::Setup::Test->new;
4534             };
4535              
4536             sub ucspi_tcp {
4537 0     0 0 0 my $self = shift;
4538 0         0 my %p = validate( @_, { $self->get_std_opts },);
4539              
4540             # pre-declarations. We configure these for each platform and use them
4541             # at the end to build ucspi_tcp from source.
4542              
4543 0         0 my $patches = [];
4544 0         0 my @targets = ( 'make', 'make setup check' );
4545              
4546 0 0 0     0 if ( $self->conf->{install_mysql} && $self->conf->{vpopmail_mysql} ) {
4547 0         0 $patches = ["ucspi-tcp-0.88-mysql+rss.patch"];
4548             }
4549              
4550 0 0       0 if ( $OSNAME eq "freebsd" ) {
    0          
    0          
4551             # install it from ports so it is registered in the ports db
4552 0         0 $self->ucspi_tcp_freebsd();
4553             }
4554             elsif ( $OSNAME eq "darwin" ) {
4555 0         0 $patches = ["ucspi-tcp-0.88-mysql+rss-darwin.patch"];
4556 0         0 @targets = $self->ucspi_tcp_darwin();
4557             }
4558             elsif ( $OSNAME eq "linux" ) {
4559 0         0 @targets = (
4560             "echo gcc -O2 -include /usr/include/errno.h > conf-cc",
4561             "make", "make setup check"
4562             );
4563              
4564             # Need to test MySQL patch on linux before enabling it.
4565             # $patches = ['ucspi-tcp-0.88-mysql+rss.patch', 'ucspi-tcp-0.88.errno.patch'];
4566             # $patch_args = "-p0";
4567             }
4568              
4569             # see if it is installed
4570 0         0 my $tcpserver = $self->util->find_bin( "tcpserver", fatal => 0, verbose=>0 );
4571 0 0       0 if ( $tcpserver ) {
4572 0 0 0     0 if ( ! $self->conf->{install_mysql} || !$self->conf->{vpopmail_mysql} ) {
4573 0         0 $self->audit( "ucspi-tcp: install, ok (exists)" );
4574 0         0 return 2; # we don't need mysql
4575             }
4576 0         0 my $strings = $self->util->find_bin( "strings", verbose=>0 );
4577 0 0       0 if ( grep {/sql/} `$strings $tcpserver` ) {
  0         0  
4578 0         0 $self->audit( "ucspi-tcp: mysql support check, ok (exists)" );
4579 0         0 return 1;
4580             }
4581 0         0 $self->audit( "ucspi-tcp is installed but w/o mysql support, " .
4582             "compiling from sources.");
4583             }
4584              
4585             # save some bandwidth
4586 0 0       0 if ( -e "/usr/ports/distfiles/ucspi-tcp-0.88.tar.gz" ) {
4587 0         0 copy( "/usr/ports/distfiles/ucspi-tcp-0.88.tar.gz",
4588             "/usr/local/src/ucspi-tcp-0.88.tar.gz"
4589             );
4590             }
4591              
4592             $self->util->install_from_source(
4593             package => "ucspi-tcp-0.88",
4594             patches => $patches,
4595 0         0 patch_url => $self->conf->{toaster_dl_site} . $self->conf->{toaster_dl_url} . "/patches",
4596             site => 'http://cr.yp.to',
4597             url => '/ucspi-tcp',
4598             targets => \@targets,
4599             );
4600              
4601 0 0       0 return $self->util->find_bin( "tcpserver", fatal => 0, verbose => 0 ) ? 1 : 0;
4602             }
4603              
4604             sub ucspi_tcp_darwin {
4605 0     0 0 0 my $self = shift;
4606              
4607 0         0 my @targets = "echo '/opt/local' > conf-home";
4608              
4609 0 0       0 if ( $self->conf->{vpopmail_mysql} ) {
4610 0         0 my $mysql_prefix = "/opt/local";
4611 0 0       0 if ( !-d "$mysql_prefix/include/mysql" ) {
4612 0 0       0 if ( -d "/usr/include/mysql" ) {
4613 0         0 $mysql_prefix = "/usr";
4614             }
4615             }
4616 0         0 push @targets,
4617             "echo 'gcc -s -I$mysql_prefix/include/mysql -L$mysql_prefix/lib/mysql -lmysqlclient' > conf-ld";
4618 0         0 push @targets,
4619             "echo 'gcc -O2 -I$mysql_prefix/include/mysql' > conf-cc";
4620             }
4621              
4622 0         0 push @targets, "make";
4623 0         0 push @targets, "make setup";
4624 0         0 return @targets;
4625             };
4626              
4627             sub ucspi_tcp_freebsd {
4628 0     0 0 0 my $self = shift;
4629 0         0 $self->freebsd->install_port( "ucspi-tcp",
4630             flags => "BATCH=yes WITH_RSS_DIFF=1",
4631             options => "#\n# This file is auto-generated by 'make config'.
4632             # No user-servicable parts inside!
4633             # Options for ucspi-tcp-0.88_2
4634             _OPTIONS_READ=ucspi-tcp-0.88_2
4635             WITHOUT_MAN=true
4636             WITH_RSS_DIFF=true
4637             WITHOUT_SSL=true
4638             WITHOUT_RBL2SMTPD=true\n",
4639             );
4640             };
4641              
4642             sub ucspi_test {
4643 0     0 0 0 my $self = shift;
4644              
4645 0         0 print "checking ucspi-tcp binaries...\n";
4646 0         0 foreach (qw( tcprules tcpserver rblsmtpd tcpclient recordio )) {
4647 0         0 $self->test->pretty(" $_", $self->util->find_bin( $_, fatal => 0, verbose=>0 ) );
4648             }
4649              
4650 0 0 0     0 if ( $self->conf->{install_mysql} && $self->conf->{vpopmail_mysql} ) {
4651 0         0 my $tcpserver = $self->util->find_bin( "tcpserver", fatal => 0, verbose=>0 );
4652 0         0 $self->test->pretty( " tcpserver mysql support",
4653             scalar `strings $tcpserver | grep sql`
4654             );
4655             }
4656              
4657 0         0 return 1;
4658             }
4659              
4660             sub user_add {
4661 0     0 0 0 my ($self, $user, $uid, $gid, %opts) = @_;
4662              
4663 0 0       0 return if ! $user;
4664 0 0       0 return if $self->user_exists($user);
4665              
4666 0         0 my $homedir = $opts{homedir};
4667 0   0     0 my $shell = $opts{shell} || '/sbin/nologin';
4668              
4669 0         0 my $cmd;
4670 0 0       0 if ( $OSNAME eq 'linux' ) {
    0          
    0          
4671 0         0 $cmd = $self->util->find_bin( 'useradd' );
4672 0         0 $cmd .= " -s $shell";
4673 0 0       0 $cmd .= " -d $homedir" if $homedir;
4674 0 0       0 $cmd .= " -u $uid" if $uid;
4675 0 0       0 $cmd .= " -g $gid" if $gid;
4676 0         0 $cmd .= " -m $user";
4677             }
4678             elsif ( $OSNAME eq 'freebsd' ) {
4679 0         0 $cmd = $self->util->find_bin( 'pw' );
4680 0         0 $cmd .= " useradd -n $user -s $shell";
4681 0 0       0 $cmd .= " -d $homedir" if $homedir;
4682 0 0       0 $cmd .= " -u $uid " if $uid;
4683 0 0       0 $cmd .= " -g $gid " if $gid;
4684 0         0 $cmd .= " -m -h-";
4685             }
4686             elsif ( $OSNAME eq 'darwin' ) {
4687 0         0 $cmd = $self->util->find_bin( 'dscl', fatal => 0 );
4688 0         0 my $path = "/users/$user";
4689 0 0       0 if ( $cmd ) {
4690 0         0 $self->util->syscmd( "$cmd . -create $path" );
4691 0         0 $self->util->syscmd( "$cmd . -createprop $path uid $uid");
4692 0         0 $self->util->syscmd( "$cmd . -createprop $path gid $gid");
4693 0         0 $self->util->syscmd( "$cmd . -createprop $path shell $shell" );
4694 0 0       0 $self->util->syscmd( "$cmd . -createprop $path home $homedir" ) if $homedir;
4695 0         0 $self->util->syscmd( "$cmd . -createprop $path passwd '*'" );
4696             }
4697             else {
4698 0         0 $cmd = $self->util->find_bin( 'niutil' );
4699 0         0 $self->util->syscmd( "$cmd -createprop . $path uid $uid");
4700 0         0 $self->util->syscmd( "$cmd -createprop . $path gid $gid");
4701 0         0 $self->util->syscmd( "$cmd -createprop . $path shell $shell");
4702 0 0       0 $self->util->syscmd( "$cmd -createprop . $path home $homedir" ) if $homedir;
4703 0         0 $self->util->syscmd( "$cmd -createprop . $path _shadow_passwd");
4704 0         0 $self->util->syscmd( "$cmd -createprop . $path passwd '*'");
4705             };
4706 0         0 return 1;
4707             }
4708             else {
4709 0         0 warn "cannot add user on OS $OSNAME\n";
4710 0         0 return;
4711             };
4712 0         0 return $self->util->syscmd( $cmd );
4713             };
4714              
4715             sub user_exists {
4716 0     0 0 0 my $self = shift;
4717 0 0       0 my $user = lc(shift) or die "missing user";
4718 0         0 my $uid = getpwnam($user);
4719 0 0 0     0 return ( $uid && $uid > 0 ) ? $uid : undef;
4720             };
4721              
4722             sub vpopmail {
4723 3     3 0 950 require Mail::Toaster::Setup::Vpopmail;
4724 3         21 return Mail::Toaster::Setup::Vpopmail->new;
4725             };
4726              
4727             sub vqadmin {
4728 3     3 0 11 my $self = shift;
4729 3         7 my %p = validate( @_, { $self->get_std_opts },);
4730              
4731 3 100       18 return $p{test_ok} if defined $p{test_ok}; # for testing
4732              
4733 1 50       3 if ( ! $self->conf->{install_vqadmin} ) {
4734 1         3 $self->audit( "vqadmin: installing, skipping (disabled)" );
4735 1         3 return;
4736             }
4737              
4738 0   0       my $cgi = $self->conf->{toaster_cgi_bin} || "/usr/local/www/cgi-bin";
4739 0   0       my $data = $self->conf->{toaster_http_docs} || "/usr/local/www/data";
4740              
4741 0 0 0       if ( $cgi && $cgi =~ /\/usr\/local\/(.*)$/ ) {
4742 0           $cgi = $1;
4743 0 0         chop $cgi if $cgi =~ /\/$/; # remove trailing /
4744             }
4745              
4746 0 0         if ( $data =~ /\/usr\/local\/(.*)$/ ) {
4747 0 0         chop $data if $data =~ /\/$/; # remove trailing /
4748 0           $data = $1;
4749             }
4750              
4751 0           my @defs = 'CGIBINDIR="' . $cgi . '"';
4752 0           push @defs, 'WEBDATADIR="' . $data . '"';
4753              
4754 0 0         return $p{test_ok} if defined $p{test_ok}; # for testing only
4755              
4756 0 0         if ( $OSNAME eq "freebsd" ) {
4757 0 0         $self->freebsd->install_port( "vqadmin", flags => join( ",", @defs ) )
4758             and return 1;
4759             }
4760              
4761 0           my $make = $self->util->find_bin("gmake", fatal=>0, verbose=>0);
4762 0   0       $make ||= $self->util->find_bin("make", fatal=>0, verbose=>0);
4763              
4764 0           print "trying to build vqadmin from sources\n";
4765              
4766 0           $self->util->install_from_source(
4767             package => "vqadmin",
4768             site => "http://vpopmail.sf.net",
4769             url => "/downloads",
4770             targets => [ "./configure ", $make, "$make install-strip" ],
4771             source_sub_dir => 'mail',
4772             );
4773             }
4774              
4775             sub webmail {
4776 0     0 0   my $self = shift;
4777 0           my %p = validate( @_, { $self->get_std_opts },);
4778              
4779             # if the cgi_files dir is not available, we can't do much.
4780 0           my $tver = $Mail::Toaster::VERSION;
4781 0           my $dir = './cgi_files';
4782 0 0         if ( ! -d $dir ) {
4783 0 0         if ( -d "/usr/local/src/Mail-Toaster-$tver/cgi_files" ) {
4784 0           $dir = "/usr/local/src/Mail-Toaster-$tver/cgi_files";
4785             }
4786             };
4787              
4788 0 0         return $self->error( "You need to run this target while in the Mail::Toaster directory!\n"
4789             . "Try this instead:
4790              
4791             cd /usr/local/src/Mail-Toaster-$tver
4792             bin/toaster_setup.pl -s webmail
4793              
4794             You are currently in " . Cwd::cwd ) if ! -d $dir;
4795              
4796             # set the hostname in mt-script.js
4797 0           my $hostname = $self->conf->{toaster_hostname};
4798              
4799 0           my @lines = $self->util->file_read("$dir/mt-script.js");
4800 0           foreach my $line ( @lines ) {
4801 0 0         if ( $line =~ /\Avar mailhost / ) {
4802 0           $line = qq{var mailhost = 'https://$hostname'};
4803             };
4804             }
4805 0           $self->util->file_write( "$dir/mt-script.js", lines => \@lines );
4806              
4807 0   0       my $htdocs = $self->conf->{toaster_http_docs} || '/usr/local/www/toaster';
4808 0 0         my $rsync = $self->rsync() or return;
4809              
4810 0           my $cmd = "$rsync -av $dir/ $htdocs/";
4811 0           print "about to run cmd: $cmd\n";
4812              
4813 0           print "\a";
4814 0 0         return if ! $self->util->yes_or_no(
4815             "\n\n\t CAUTION! DANGER! CAUTION!
4816              
4817             This action will install the Mail::Toaster webmail interface. Doing
4818             so may overwrite existing files in $htdocs. Is is safe to proceed?\n\n",
4819             timeout => 60,
4820             );
4821              
4822 0           $self->util->syscmd( $cmd );
4823 0           return 1;
4824             };
4825              
4826             1;
4827             __END__;
4828              
4829              
4830             =head1 NAME
4831              
4832             Mail::Toaster::Setup - methods to configure and build all the components of a modern email server.
4833              
4834             =head1 DESCRIPTION
4835              
4836             The meat and potatoes of toaster_setup.pl. This is where the majority of the work gets done. Big chunks of the code and logic for getting all the various applications and scripts installed and configured resides in here.
4837              
4838              
4839             =head1 METHODS
4840              
4841             All documented methods in this package (shown below) accept two optional arguments, verbose and fatal. Setting verbose to zero will supress nearly all informational and debugging output. If you want more output, simply pass along verbose=>1 and status messages will print out. Fatal allows you to override the default behaviour of these methods, which is to die upon error. Each sub returns 0 if the action failed and 1 for success.
4842              
4843             arguments required:
4844             varies (most require conf)
4845              
4846             arguments optional:
4847             verbose - print status messages
4848             fatal - die on errors (default)
4849              
4850             result:
4851             0 - failure
4852             1 - success
4853              
4854             =over
4855              
4856             =item new
4857              
4858             To use any methods in Mail::Toaster::Setup, you must create a setup object:
4859              
4860             use Mail::Toaster::Setup;
4861             my $setup = Mail::Toaster::Setup->new;
4862              
4863             From there you can run any of the following methods via $setup->method as documented below.
4864              
4865             Many of the methods require $conf, which is a hashref containing the contents of toaster-watcher.conf.
4866              
4867             =item clamav
4868              
4869             Install ClamAV, configure the startup and config files, download the latest virus definitions, and start up the daemons.
4870              
4871              
4872             =item config - personalize your toaster-watcher.conf settings
4873              
4874             There are a subset of the settings in toaster-watcher.conf which must be personalized for your server. Things like the hostname, where you store your configuration files, html documents, passwords, etc. This function checks to make sure these settings have been changed and prompts for any necessary changes.
4875              
4876             required arguments:
4877             conf
4878              
4879              
4880             =item config_tweaks
4881              
4882             Makes changes to the config file, dynamically based on detected circumstances such as a jailed hostname, or OS platform. Platforms like FreeBSD, Darwin, and Debian have package management capabilities. Rather than installing software via sources, we prefer to try using the package manager first. The toaster-watcher.conf file typically includes the latest stable version of each application to install. This subroutine will replace those version numbers with with 'port', 'package', or other platform specific tweaks.
4883              
4884             =item daemontools
4885              
4886             Fetches sources from DJB's web site and installs daemontools, per his instructions.
4887              
4888             =item dependencies
4889              
4890             $setup->dependencies( );
4891              
4892             Installs a bunch of dependency programs that are needed by other programs we will install later during the build of a Mail::Toaster. You can install these yourself if you would like, this does not do anything special beyond installing them:
4893              
4894             gdbm, setquota, expect, maildrop, autorespond, qmail, qmailanalog, daemontools, openldap-client, Crypt::OpenSSL-RSA, DBI, DBD::mysql.
4895              
4896             required arguments:
4897             conf
4898              
4899             result:
4900             1 - success
4901             0 - failure
4902              
4903              
4904             =item djbdns
4905              
4906             Fetches djbdns, compiles and installs it.
4907              
4908             $setup->djbdns( );
4909              
4910             required arguments:
4911             conf
4912              
4913             result:
4914             1 - success
4915             0 - failure
4916              
4917              
4918             =item expect
4919              
4920             Expect is a component used by courier-imap and sqwebmail to enable password changing via those tools. Since those do not really work with a Mail::Toaster, we could live just fine without it, but since a number of FreeBSD ports want it installed, we install it without all the extra X11 dependencies.
4921              
4922              
4923             =item ezmlm
4924              
4925             Installs Ezmlm-idx. This also tweaks the port Makefile so that it will build against MySQL 4.0 libraries if you don't have MySQL 3 installed. It also copies the sample config files into place so that you have some default settings.
4926              
4927             $setup->ezmlm( );
4928              
4929             required arguments:
4930             conf
4931              
4932             result:
4933             1 - success
4934             0 - failure
4935              
4936              
4937             =item filtering
4938              
4939             Installs SpamAssassin, ClamAV, simscan, QmailScanner, maildrop, procmail, and programs that support the aforementioned ones. See toaster-watcher.conf for options that allow you to customize which programs are installed and any options available.
4940              
4941             $setup->filtering();
4942              
4943              
4944             =item maillogs
4945              
4946             Installs the maillogs script, creates the logging directories (toaster_log_dir/), creates the qmail supervise dirs, installs maillogs as a log post-processor and then builds the corresponding service/log/run file to use with each post-processor.
4947              
4948             $setup->maillogs();
4949              
4950              
4951             =item startup_script
4952              
4953             Sets up the supervised mail services for Mail::Toaster
4954              
4955             $setup->startup_script( );
4956              
4957             If they don't already exist, this sub will create:
4958              
4959             daemontools service directory (default /var/service)
4960             symlink to the services script
4961              
4962             The services script allows you to run "services stop" or "services start" on your system to control the supervised daemons (qmail-smtpd, qmail-pop3, qmail-send, qmail-submit). It affects the following files:
4963              
4964             $prefix/etc/rc.d/[svscan|services].sh
4965             $prefix/sbin/services
4966              
4967              
4968             =item test
4969              
4970             Run a variety of tests to verify that your Mail::Toaster installation is working correctly.
4971              
4972              
4973             =back
4974              
4975              
4976             =head1 DEPENDENCIES
4977              
4978             IO::Socket::SSL
4979              
4980              
4981             =head1 AUTHOR
4982              
4983             Matt Simerson - matt@tnpi.net
4984              
4985              
4986             =head1 SEE ALSO
4987              
4988             The following are all perldoc pages:
4989              
4990             Mail::Toaster
4991             Mail::Toaster::Conf
4992             toaster.conf
4993             toaster-watcher.conf
4994              
4995             http://mail-toaster.org/
4996              
4997             =cut