Filename | /usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf/SQL.pm |
Statements | Executed 14 statements in 1.92ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 45µs | 241µs | BEGIN@44 | Mail::SpamAssassin::Conf::SQL::
1 | 1 | 1 | 26µs | 40µs | BEGIN@46 | Mail::SpamAssassin::Conf::SQL::
1 | 1 | 1 | 24µs | 31µs | BEGIN@48 | Mail::SpamAssassin::Conf::SQL::
1 | 1 | 1 | 23µs | 102µs | BEGIN@49 | Mail::SpamAssassin::Conf::SQL::
1 | 1 | 1 | 21µs | 59µs | BEGIN@47 | Mail::SpamAssassin::Conf::SQL::
1 | 1 | 1 | 20µs | 104µs | BEGIN@51 | Mail::SpamAssassin::Conf::SQL::
0 | 0 | 0 | 0s | 0s | __ANON__[:104] | Mail::SpamAssassin::Conf::SQL::
0 | 0 | 0 | 0s | 0s | load | Mail::SpamAssassin::Conf::SQL::
0 | 0 | 0 | 0s | 0s | load_modules | Mail::SpamAssassin::Conf::SQL::
0 | 0 | 0 | 0s | 0s | load_with_dbi | Mail::SpamAssassin::Conf::SQL::
0 | 0 | 0 | 0s | 0s | new | Mail::SpamAssassin::Conf::SQL::
0 | 0 | 0 | 0s | 0s | sa_die | Mail::SpamAssassin::Conf::SQL::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | # <@LICENSE> | ||||
2 | # Licensed to the Apache Software Foundation (ASF) under one or more | ||||
3 | # contributor license agreements. See the NOTICE file distributed with | ||||
4 | # this work for additional information regarding copyright ownership. | ||||
5 | # The ASF licenses this file to you under the Apache License, Version 2.0 | ||||
6 | # (the "License"); you may not use this file except in compliance with | ||||
7 | # the License. You may obtain a copy of the License at: | ||||
8 | # | ||||
9 | # http://www.apache.org/licenses/LICENSE-2.0 | ||||
10 | # | ||||
11 | # Unless required by applicable law or agreed to in writing, software | ||||
12 | # distributed under the License is distributed on an "AS IS" BASIS, | ||||
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
14 | # See the License for the specific language governing permissions and | ||||
15 | # limitations under the License. | ||||
16 | # </@LICENSE> | ||||
17 | |||||
18 | =head1 NAME | ||||
19 | |||||
20 | Mail::SpamAssassin::Conf::SQL - load SpamAssassin scores from SQL database | ||||
21 | |||||
22 | =head1 SYNOPSIS | ||||
23 | |||||
24 | (see Mail::SpamAssassin) | ||||
25 | |||||
26 | |||||
27 | =head1 DESCRIPTION | ||||
28 | |||||
29 | Mail::SpamAssassin is a module to identify spam using text analysis and | ||||
30 | several internet-based realtime blacklists. | ||||
31 | |||||
32 | This class is used internally by SpamAssassin to load scores from an SQL | ||||
33 | database. Please refer to the C<Mail::SpamAssassin> documentation for public | ||||
34 | interfaces. | ||||
35 | |||||
36 | =head1 METHODS | ||||
37 | |||||
38 | =over 4 | ||||
39 | |||||
40 | =cut | ||||
41 | |||||
42 | package Mail::SpamAssassin::Conf::SQL; | ||||
43 | |||||
44 | 2 | 83µs | 2 | 437µs | # spent 241µs (45+196) within Mail::SpamAssassin::Conf::SQL::BEGIN@44 which was called:
# once (45µs+196µs) by Mail::SpamAssassin::BEGIN@72 at line 44 # spent 241µs making 1 call to Mail::SpamAssassin::Conf::SQL::BEGIN@44
# spent 196µs making 1 call to Exporter::import |
45 | |||||
46 | 2 | 68µs | 2 | 54µs | # spent 40µs (26+14) within Mail::SpamAssassin::Conf::SQL::BEGIN@46 which was called:
# once (26µs+14µs) by Mail::SpamAssassin::BEGIN@72 at line 46 # spent 40µs making 1 call to Mail::SpamAssassin::Conf::SQL::BEGIN@46
# spent 14µs making 1 call to strict::import |
47 | 2 | 69µs | 2 | 97µs | # spent 59µs (21+38) within Mail::SpamAssassin::Conf::SQL::BEGIN@47 which was called:
# once (21µs+38µs) by Mail::SpamAssassin::BEGIN@72 at line 47 # spent 59µs making 1 call to Mail::SpamAssassin::Conf::SQL::BEGIN@47
# spent 38µs making 1 call to warnings::import |
48 | 2 | 74µs | 2 | 38µs | # spent 31µs (24+7) within Mail::SpamAssassin::Conf::SQL::BEGIN@48 which was called:
# once (24µs+7µs) by Mail::SpamAssassin::BEGIN@72 at line 48 # spent 31µs making 1 call to Mail::SpamAssassin::Conf::SQL::BEGIN@48
# spent 7µs making 1 call to bytes::import |
49 | 2 | 67µs | 2 | 180µs | # spent 102µs (23+79) within Mail::SpamAssassin::Conf::SQL::BEGIN@49 which was called:
# once (23µs+79µs) by Mail::SpamAssassin::BEGIN@72 at line 49 # spent 102µs making 1 call to Mail::SpamAssassin::Conf::SQL::BEGIN@49
# spent 78µs making 1 call to re::import |
50 | |||||
51 | 1 | 2µs | # spent 104µs (20+83) within Mail::SpamAssassin::Conf::SQL::BEGIN@51 which was called:
# once (20µs+83µs) by Mail::SpamAssassin::BEGIN@72 at line 53 | ||
52 | @ISA | ||||
53 | 1 | 1.54ms | 2 | 187µs | }; # spent 104µs making 1 call to Mail::SpamAssassin::Conf::SQL::BEGIN@51
# spent 83µs making 1 call to vars::import |
54 | |||||
55 | 1 | 8µs | @ISA = qw(); | ||
56 | |||||
57 | ########################################################################### | ||||
58 | |||||
59 | sub new { | ||||
60 | my $class = shift; | ||||
61 | $class = ref($class) || $class; | ||||
62 | my ($main) = @_; | ||||
63 | |||||
64 | my $self = { | ||||
65 | 'main' => $main | ||||
66 | }; | ||||
67 | |||||
68 | bless ($self, $class); | ||||
69 | $self; | ||||
70 | } | ||||
71 | |||||
72 | ########################################################################### | ||||
73 | |||||
74 | sub load_modules { # static | ||||
75 | eval { | ||||
76 | require DBI; | ||||
77 | }; | ||||
78 | |||||
79 | # do any other preloading that will speed up operation | ||||
80 | } | ||||
81 | |||||
82 | ########################################################################### | ||||
83 | |||||
84 | =item $f->load ($username) | ||||
85 | |||||
86 | Read configuration paramaters from SQL database and parse scores from it. | ||||
87 | |||||
88 | =back | ||||
89 | |||||
90 | =cut | ||||
91 | |||||
92 | sub load { | ||||
93 | my ($self, $username) = @_; | ||||
94 | |||||
95 | my $conf = $self->{main}->{conf}; | ||||
96 | my $dsn = $conf->{user_scores_dsn}; | ||||
97 | if (!defined($dsn) || $dsn eq '') { | ||||
98 | dbg("config: no DSN defined; skipping sql"); | ||||
99 | return 1; | ||||
100 | } | ||||
101 | |||||
102 | eval { | ||||
103 | # make sure we can see croak messages from DBI | ||||
104 | local $SIG{'__DIE__'} = sub { die "$_[0]"; }; | ||||
105 | require DBI; | ||||
106 | load_with_dbi($self, $username, $dsn); | ||||
107 | 1; | ||||
108 | } or do { | ||||
109 | my $eval_stat = $@ ne '' ? $@ : "errno=$!"; chomp $eval_stat; | ||||
110 | if ($conf->{user_scores_fail_to_global}) { | ||||
111 | info("config: failed to load user (%s) scores from SQL database, ". | ||||
112 | "using a global default: %s", $username, $eval_stat); | ||||
113 | return 1; | ||||
114 | } else { | ||||
115 | warn sprintf( | ||||
116 | "config: failed to load user (%s) scores from SQL database: %s\n", | ||||
117 | $username, $eval_stat); | ||||
118 | return 0; | ||||
119 | } | ||||
120 | }; | ||||
121 | return 1; | ||||
122 | } | ||||
123 | |||||
124 | sub load_with_dbi { | ||||
125 | my ($self, $username, $dsn) = @_; | ||||
126 | |||||
127 | my $main = $self->{main}; | ||||
128 | my $conf = $main->{conf}; | ||||
129 | my $dbuser = $conf->{user_scores_sql_username}; | ||||
130 | my $dbpass = $conf->{user_scores_sql_password}; | ||||
131 | my $custom_query = $conf->{user_scores_sql_custom_query}; | ||||
132 | |||||
133 | my $f_preference = 'preference'; | ||||
134 | my $f_value = 'value'; | ||||
135 | my $f_username = 'username'; | ||||
136 | my $f_table = 'userpref'; | ||||
137 | |||||
138 | my $dbh = DBI->connect($dsn, $dbuser, $dbpass, {'PrintError' => 0}); | ||||
139 | |||||
140 | if ($dbh) { | ||||
141 | my $sql; | ||||
142 | if (defined($custom_query)) { | ||||
143 | $sql = $custom_query; | ||||
144 | my $quoted_username = $dbh->quote($username); | ||||
145 | my ($mailbox, $domain) = split('@', $username); | ||||
146 | my $quoted_mailbox = $dbh->quote($mailbox); | ||||
147 | my $quoted_domain = $dbh->quote($domain); | ||||
148 | |||||
149 | $sql =~ s/_USERNAME_/$quoted_username/g; | ||||
150 | $sql =~ s/_TABLE_/$f_table/g; | ||||
151 | $sql =~ s/_MAILBOX_/$quoted_mailbox/g; | ||||
152 | $sql =~ s/_DOMAIN_/$quoted_domain/g; | ||||
153 | } | ||||
154 | else { | ||||
155 | $sql = "select $f_preference, $f_value from $f_table where ". | ||||
156 | "$f_username = ".$dbh->quote($username). | ||||
157 | " or $f_username = '\@GLOBAL' order by $f_username asc"; | ||||
158 | } | ||||
159 | dbg("config: Conf::SQL: executing SQL: $sql"); | ||||
160 | my $sth = $dbh->prepare($sql); | ||||
161 | if ($sth) { | ||||
162 | my $rv = $sth->execute(); | ||||
163 | if ($rv) { | ||||
164 | dbg("config: retrieving prefs for $username from SQL server"); | ||||
165 | my @row; | ||||
166 | my $config_text = ''; | ||||
167 | while (@row = $sth->fetchrow_array()) { | ||||
168 | $config_text .= (defined($row[0]) ? $row[0] : '') . "\t" . | ||||
169 | (defined($row[1]) ? $row[1] : '') . "\n"; | ||||
170 | } | ||||
171 | if ($config_text ne '') { | ||||
172 | $conf->{main} = $main; | ||||
173 | $conf->parse_scores_only($config_text); | ||||
174 | delete $conf->{main}; | ||||
175 | } | ||||
176 | $sth->finish(); | ||||
177 | undef $sth; | ||||
178 | } | ||||
179 | else { | ||||
180 | die "config: SQL error: $sql\n".$sth->errstr."\n"; | ||||
181 | } | ||||
182 | } | ||||
183 | else { | ||||
184 | die "config: SQL error: " . $dbh->errstr . "\n"; | ||||
185 | } | ||||
186 | $dbh->disconnect(); | ||||
187 | } | ||||
188 | else { | ||||
189 | die "config: SQL error: " . DBI->errstr . "\n"; | ||||
190 | } | ||||
191 | } | ||||
192 | |||||
193 | ########################################################################### | ||||
194 | |||||
195 | sub sa_die { Mail::SpamAssassin::sa_die(@_); } | ||||
196 | |||||
197 | ########################################################################### | ||||
198 | |||||
199 | 1 | 8µs | 1; |