File Coverage

blib/lib/Qmail/Mysql.pm
Criterion Covered Total %
statement 27 181 14.9
branch 4 38 10.5
condition 1 27 3.7
subroutine 7 29 24.1
pod 11 12 91.6
total 50 287 17.4


line stmt bran cond sub pod time code
1             package Qmail::Mysql;
2              
3              
4 1     1   23860 use 5.006;
  1         4  
  1         49  
5 1     1   6 use strict;
  1         2  
  1         40  
6 1     1   5 use warnings;
  1         8  
  1         43  
7 1     1   6 use Carp;
  1         2  
  1         273  
8              
9 1     1   5157 use DBI;
  1         26400  
  1         149  
10 1     1   13 use File::Path;
  1         2  
  1         3243  
11              
12              
13             $Qmail::Mysql::VERSION = '0.02';
14              
15              
16             # Fields that can be set in new method, with defaults
17             my %fields =(
18             sql_control_file => '/var/qmail/control/sqlserver',
19             mailbox_base => '/var/spool/pop/users',
20             password_type => 'Password',
21             multihosting => 0,
22             multihosting_join => '@',
23             );
24              
25             sub new
26             {
27 1     1 0 101 my ($proto,%options) = @_;
28 1   33     7 my $class = ref($proto) || $proto;
29 1         8 my $self = {
30             %fields};
31 1         5 while (my ($key,$value) = each(%options)) {
32 5 50       10 if (exists($fields{$key})) {
33 5 50       17 $self->{$key} = $value if (defined $value);
34             } else {
35 0         0 die $class . "::new: invalid option '$key'\n";
36             }
37             }
38 1         8 foreach (keys(%fields)) {
39 5 50       12 die $class . "::new: must specify value for $_"
40             if (!defined $self->{$_});
41             }
42 1 50       171 die $class . "::new: Unable to file sql control file at " .
43             $self->{sql_control_file} if (!-e $self->{sql_control_file});
44 0           bless $self, $class;
45 0           $self->_init;
46 0           return $self;
47             }
48              
49             sub _init {
50 0     0     my $self = shift;
51 0           $self->_parse_control();
52             }
53              
54             sub _parse_control() {
55 0     0     my $self = shift;
56 0 0         open(SQLCTL,$self->{sql_control_file})
57             or die "Unable to open $self->{sql_control_file}";
58 0           my $line;
59 0           while () {
60 0           $line++;
61 0           s/^\s*//;
62 0           s/\s*^//;
63 0           my ($key,$val) = split(/\s+/);
64 0 0 0       die "Invalid control file format in " .
65             "$self->{sql_control_file} at line $line"
66             if (!defined $key || !defined $val);
67 0           $self->{_db}->{$key} = $val;
68             }
69 0           close(SQLCTL);
70             # check minimum data
71 0 0         die "DB Host name not found in $self->{sql_control_file}"
72             if (!exists $self->{_db}->{server});
73 0 0         die "DB login name not found in $self->{sql_control_file}"
74             if (!exists $self->{_db}->{login});
75 0 0         die "DB password not found in $self->{sql_control_file}"
76             if (!exists $self->{_db}->{password});
77 0 0         die "DB name not found in $self->{sql_control_file}"
78             if (!exists $self->{_db}->{db});
79             }
80              
81             sub connect {
82 0     0 1   my $self = shift;
83 0           my $database = $self->{_db}->{db};
84 0           my $hostname = $self->{_db}->{server};
85            
86 0           my $dsn = "DBI:mysql:database=$database;host=$hostname";
87 0 0         $self->{dbh} = DBI->connect($dsn, $self->{_db}->{login},
88             $self->{_db}->{password}) or
89             die "Unable to connect to qmail database using login " .
90             "information in $self->{sql_control_file}";
91             }
92              
93             sub disconnect {
94 0     0 1   my $self = shift;
95 0 0         $self->{dbh}->disconnect if defined $self->{dbh};
96             }
97              
98             sub rcpt_add {
99 0     0 1   my $self = shift;
100 0           my $rcpt_host = $self->_q(shift);
101 0           my $sql = qq|insert into rcpthosts (host) VALUES ($rcpt_host)|;
102 0           $self->_do($sql);
103             }
104              
105             sub rcpt_exists {
106 0     0 1   my $self = shift;
107 0           my $rcpt_host = $self->_q(shift);
108 0           my $sql = qq|select count(*) from rcpthosts where host = $rcpt_host|;
109 0           return $self->{dbh}->selectrow_arrayref($sql)->[0];
110             }
111              
112             sub rcpt_del {
113 0     0 1   my $self = shift;
114 0           my $rcpt_host = $self->_q(shift);
115 0           my $sql = qq|delete from rcpthosts where host = $rcpt_host|;
116 0           $self->_do($sql);
117             }
118              
119             sub mail_add {
120 0     0 1   my $self = shift;
121 0           my $vuser = shift;
122 0           my $vhost = shift;
123 0           my $pass = shift;
124 0   0       my $mbox = shift || $self->_mbox($vuser,$vhost);
125 0   0       my $mbox_path = shift || $self->_mbox_path($vuser,$vhost);
126 0   0       my $qmaild_id = shift || (getpwnam('qmaild'))[2];
127 0   0       my $qmail_id = shift || (getpwnam('qmailr'))[3];
128              
129             # check existence of mbox_base and virtual base path
130 0           $self->_check_mbox_base($vhost,$qmaild_id,$qmail_id);
131             # create user qmail dirs
132 0           foreach (('','Maildir','Maildir/cur','Maildir/new','Maildir/tmp')) {
133 0 0         my $mask = $_ eq '' ? 0700 : 0711;
134 0           $self->_make_qmail_dir($mbox_path ."/$_",$qmaild_id,$qmail_id,$mask);
135             }
136             # add user to db
137             # add user to virtual table
138 0           $self->_table_virtual_add($mbox,$vuser,$vhost);
139             # add user to mailbox table
140 0           $self->_table_mailbox_add($mbox,$qmaild_id,$qmail_id,$mbox_path,$pass);
141              
142             }
143              
144             sub mail_exists {
145 0     0 1   my $self = shift;
146 0           my $vuser = shift;
147 0           my $vhost = shift;
148 0   0       my $mbox = shift || $self->_mbox($vuser,$vhost);
149 0           $mbox = $self->_q($mbox);
150 0           my $sql = qq|select count(*) from mailbox where username = $mbox|;
151 0           return $self->{dbh}->selectrow_arrayref($sql)->[0];
152             }
153              
154             sub mail_del {
155 0     0 1   my $self = shift;
156 0           my $vuser = shift;
157 0           my $vhost = shift;
158 0   0       my $mbox = shift || $self->_mbox($vuser,$vhost);
159            
160 0           $mbox = $self->_q($mbox);
161 0           my $sql = qq|select home from mailbox where username = $mbox|;
162 0           my $home = $self->{dbh}->selectrow_arrayref($sql)->[0];
163 0           $sql = qq|delete from mailbox where username = $mbox|;
164 0           $self->_do($sql);
165 0           $sql = qq|delete from virtual where username = $mbox|;
166 0           $self->_do($sql);
167 0           rmtree($home);
168              
169            
170             }
171              
172             sub alias_add {
173 0     0 1   my $self = shift;
174 0           my $alias = shift;
175 0           my $mail = shift;
176 0           my ($au,$ah) = split(/\@/,$alias);
177 0           my ($mu,$mh) = split(/\@/,$mail);
178 0           $alias = $self->_q($alias);
179 0           $mu = $self->_q($mu);
180 0           $mh = $self->_q($mh);
181             # aggiunta utente alla tabella virtual
182 0           $self->_table_virtual_add($self->_mbox($au,$ah),$au,$ah);
183 0           my $sql = qq|insert into alias (username,alias,alias_username,
184             alias_host) VALUES ('alias',$alias,$mu,$mh)|;
185 0           $self->_do($sql);
186             }
187              
188             sub alias_exists {
189 0     0 1   my $self = shift;
190 0           my $alias = shift;
191 0           my $mail = shift;
192 0           my ($au,$ah) = split(/\@/,$mail);
193 0           $alias = $self->_q($alias);
194 0           $au = $self->_q($au);
195 0           $ah = $self->_q($ah);
196 0           my $sql = qq|select count(*) from alias where username = 'alias'
197             and alias = $alias and alias_username = $au
198             and alias_host = $ah|;
199 0           return $self->{dbh}->selectrow_arrayref($sql)->[0];
200             }
201              
202             sub alias_del {
203 0     0 1   my $self = shift;
204 0           my $alias = shift;
205 0           my $mail = shift;
206 0           my ($au,$ah) = split(/\@/,$alias);
207 0           my ($mu,$mh) = split(/\@/,$mail);
208 0           $alias = $self->_q($alias);
209 0           $mu = $self->_q($mu);
210 0           $mh = $self->_q($mh);
211 0           my $mbox = $self->_q($self->_mbox($au,$ah));
212 0           my $sql = qq|delete from alias where username = 'alias'
213             and alias = $alias and alias_username = $mu
214             and alias_host = $mh|;
215 0           $self->_do($sql);
216 0           $sql = qq|delete from virtual where username = $mbox|;
217 0           $self->_do($sql);
218             }
219              
220             sub _table_virtual_add {
221 0     0     my $self = shift;
222 0           my $mbox = $self->_q(shift);
223 0           my $vuser = $self->_q(shift);
224 0           my $vhost = $self->_q(shift);
225 0           my $sql = qq|insert into virtual
226             (username,virtual_username,virtual_host) VALUES
227             ($mbox,$vuser,$vhost)|;
228 0           $self->_do($sql);
229             }
230              
231             sub _table_mailbox_add {
232 0     0     my $self = shift;
233 0           my $mbox = $self->_q(shift);
234 0           my $qusr = $self->_q(shift);
235 0           my $qgrp = $self->_q(shift);
236 0           my $mbox_p = $self->_q(shift);
237 0           my $pass = $self->_q(shift);
238              
239 0           my $pass_t = $self->_q($self->{password_type});
240 0           my $sql = qq|insert into mailbox
241             (username,uid,gid,home,password,password_type) VALUES
242             ($mbox,$qusr,$qgrp,$mbox_p,$pass,$pass_t)|;
243 0           $self->_do($sql);
244             }
245              
246             sub _mbox {
247 0     0     my $self = shift;
248 0           my $vuser = shift;
249 0           my $vhost = shift;
250 0 0         return $self->{multihosting}
251             ? $vuser . $self->{multihosting_join} . $vhost
252             : $vuser;
253             }
254              
255             sub _mbox_path {
256 0     0     my $self = shift;
257 0           my $vuser = shift;
258 0           my $vhost = shift;
259 0 0         return $self->{multihosting}
260             ? $self->{mailbox_base} . "/$vhost/$vuser"
261             : $self->{mailbox_base} . "/$vuser";
262             }
263              
264             sub _check_mbox_base {
265 0     0     my $self = shift;
266 0           my $vhost = shift;
267 0           my $quser = shift;
268 0           my $qgrp = shift;
269              
270 0           my $dir = $self->{mailbox_base};
271 0 0         $self->_make_qmail_dir( $dir,$quser,$qgrp,0700) if (!-e $dir);
272 0           $dir .= "/$vhost";
273 0 0 0       $self->_make_qmail_dir( $dir,$quser,$qgrp,0700)
274             if ($self->{multihosting} && !-e $dir);
275             }
276              
277             sub _make_qmail_dir {
278 0     0     my $self = shift;
279 0           my $dir = shift;
280 0           my $quser = shift;
281 0           my $qgrp = shift;
282 0           my $mask = shift;
283              
284 0           eval { mkpath($dir,0,$mask) };
  0            
285 0 0         if ($@) { die "Couldn't create $dir: $@"; }
  0            
286 0           chown $quser,$qgrp,$dir;
287              
288             }
289              
290             sub _q {
291 0     0     my $self = shift;
292 0           return $self->{dbh}->quote(shift);
293             }
294              
295              
296             sub _do {
297 0     0     my $self = shift;
298 0           my $sql = shift;
299 0 0         $self->{dbh}->do($sql) or die "Unable to execute $sql";
300             }
301              
302             sub DESTROY {
303 0     0     my $self = shift;
304 0           $self->disconnect;
305             # Enter here your code
306             }