| 101 | | my %sort = (); |
| 102 | | $sort{'ham'} = "score DESC"; # puts the high scores at the top |
| 103 | | $sort{'spam'} = "score ASC"; # puts the low scroes at the top |
| 104 | | $sort{'virus'} = "received_date DESC"; |
| 105 | | $sort{'banned_file'} = "received_date DESC"; |
| 106 | | $sort{'bad_header'} = "received_date DESC"; |
| | 100 | my %sort = ( |
| | 101 | ham => "score DESC", # puts the high scores at the top |
| | 102 | spam => "score ASC", # puts the low scroes at the top |
| | 103 | virus => "received_date DESC", |
| | 104 | banned_file => "received_date DESC", |
| | 105 | bad_header => "received_date DESC", |
| | 106 | ); |
| 124 | | |
| 125 | | # The organization of this file makes this a bit obtuse |
| 126 | | my $isPg = 0; |
| 127 | | |
| 128 | | # Retrieve the string value associated with a key in the database.cfg file. |
| 129 | | sub get_string_key($$) |
| 130 | | { |
| 131 | | my ($file, $key) = @_; |
| 132 | | |
| 133 | | if ($file =~ /\n[ \t]*$key[ \t]*=[ \t]*\"(.*)\"/) { |
| 134 | | return ($1); |
| 135 | | } else { |
| 136 | | die ("Maia: [get_db_string_key] Unable to find $key value in $file\n"); |
| 137 | | } |
| 138 | | } |
| 139 | | |
| 140 | | # Read a single value from Maia's configuration table. |
| 141 | | sub get_config_value($$) { |
| 142 | | my($dbh, $key) = @_; |
| 143 | | my($sth, @row, $select); |
| 144 | | my $value = undef; |
| 145 | | |
| 146 | | $select = "SELECT " . $key . " FROM maia_config WHERE id = 0"; |
| 147 | | $select = $1 if $select =~ /^(.*)$/si; # untaint |
| 148 | | $sth = $dbh->prepare($select) |
| 149 | | or die (sprintf("Maia: [get_config_value] Couldn't prepare query: %s", $dbh->errstr)); |
| 150 | | $sth->execute() |
| 151 | | or die (sprintf("Maia: [get_config_value] Couldn't execute query: %s", $dbh->errstr)); |
| 152 | | if (@row = $sth->fetchrow_array()) { |
| 153 | | $value = $row[0]; |
| 154 | | } |
| 155 | | $sth->finish; |
| 156 | | |
| 157 | | return $value; |
| 158 | | } |
| 159 | | |
| 160 | | #random phrase generated from password generator |
| 161 | | #credit: http://web.uconn.edu/~cdavid/cgi-bin/book/make_password_html.pl |
| 162 | | sub phrase_generate(){ |
| 163 | | my $ug = new Data::UUID; |
| 164 | | my $uuid = $ug->create_hex(); |
| 165 | | $uuid =~ s/0x(.*)/$1/; |
| 166 | | |
| 167 | | my (@passset,$rnd_passwd,$randum_num); |
| 168 | | my ($randum_num); |
| 169 | | @passset = ('A'..'Z','0'..'9'); |
| 170 | | $rnd_passwd = ""; |
| 171 | | for (my $i = 0; $i<32;$i++){ |
| 172 | | $randum_num = int(rand($#passset+1)); |
| 173 | | $rnd_passwd .= @passset[$randum_num]; |
| 174 | | } |
| 175 | | |
| 176 | | return $uuid . $rnd_passwd ; |
| 177 | | } |
| 178 | | |
| 179 | | sub generate_confirm_token($$) |
| 180 | | { |
| 181 | | my ($dbh, $maia_user_id) = @_; |
| 182 | | my $spamexpiry = get_config_value($dbh, "expiry_period"); |
| 183 | | my $hamexpiry = get_config_value($dbh, "ham_cache_expiry_period"); |
| 184 | | my $days = $spamexpiry > $hamexpiry ? $spamexpiry : $hamexpiry; |
| 185 | | |
| 186 | | my $unique_string = phrase_generate(); |
| 187 | | |
| 188 | | my $insert = "INSERT INTO maia_tokens (token_system, token, data, expires) " . |
| 189 | | "VALUES ('digest',?,?, " . |
| 190 | | ($isPg ? "NOW() + INTERVAL ? DAY" |
| 191 | | : "DATE_ADD(NOW(), INTERVAL ? DAY)") . |
| 192 | | ")"; |
| 193 | | my $sth = $dbh->prepare($insert); |
| 194 | | $sth->execute($unique_string, $maia_user_id,$days) or die (sprintf("Maia: [send-quarantine-reminders] Couldn't execute query: %s", $dbh->errstr));; |
| 195 | | |
| 196 | | return $unique_string; |
| 197 | | } |
| | 124 | sub get_string_key($$); |
| | 125 | sub get_config_value($$); |
| | 126 | sub phrase_generate(); |
| | 127 | sub generate_confirm_token($$); |
| 220 | | $select = "SELECT admin_email, " . |
| 221 | | "smtp_server, " . |
| 222 | | "smtp_port " . |
| 223 | | "FROM maia_config WHERE id = 0"; |
| 224 | | $sth = $dbh->prepare($select) |
| 225 | | or die (sprintf("Maia: [send-quarantine-reminders] Couldn't prepare query: %s", $dbh->errstr)); |
| | 150 | |
| | 151 | $query = <<"endSQL;"; |
| | 152 | SELECT admin_email, smtp_server, smtp_port |
| | 153 | FROM maia_config |
| | 154 | WHERE id = 0 |
| | 155 | endSQL; |
| | 156 | |
| | 157 | $sth = $dbh->prepare($query) |
| | 158 | or die (sprintf("Maia: [send-quarantine-digests] Couldn't prepare query: %s", $dbh->errstr)); |
| 247 | | $select = "SELECT maia_users.id, users.email " . |
| 248 | | "FROM maia_users, users " . |
| 249 | | "WHERE maia_users.primary_email_id = users.id " . |
| 250 | | "AND maia_users.quarantine_digest_interval > 0 " . |
| 251 | | "AND (maia_users.quarantine_digest_interval <= " . |
| 252 | | ($isPg ? "(( ROUND(DATE_PART('epoch', NOW())) - ROUND(DATE_PART('epoch', maia_users.last_digest_sent))) / 60)" |
| 253 | | : "((UNIX_TIMESTAMP() - UNIX_TIMESTAMP(maia_users.last_digest_sent)) / 60) ") . |
| 254 | | "OR maia_users.last_digest_sent IS NULL) " . |
| 255 | | "ORDER BY maia_users.id ASC"; |
| 256 | | my $sth3 = $dbh->prepare($select) |
| | 175 | my $unixTime = $isPg ? "( ROUND(DATE_PART('epoch', NOW())) - ROUND(DATE_PART('epoch', maia_users.last_digest_sent)))" |
| | 176 | : "(UNIX_TIMESTAMP() - UNIX_TIMESTAMP(maia_users.last_digest_sent)"; |
| | 177 | |
| | 178 | $query = <<"endSQL;"; |
| | 179 | SELECT maia_users.id, users.email |
| | 180 | FROM maia_users, users |
| | 181 | WHERE maia_users.primary_email_id = users.id |
| | 182 | AND maia_users.quarantine_digest_interval > 0 |
| | 183 | AND (maia_users.quarantine_digest_interval <= ($unixTime / 60) |
| | 184 | OR maia_users.last_digest_sent IS NULL) |
| | 185 | ORDER BY maia_users.id ASC |
| | 186 | endSQL; |
| | 187 | |
| | 188 | my $users_sth = $dbh->prepare($query) |
| 261 | | while (my @row3 = $sth3->fetchrow_array()) { |
| 262 | | $user_id = $1 if $row3[0] =~ /^(\d+)$/si; # untaint |
| 263 | | $user_email = $1 if $row3[1] =~ /^(.+@.+\..+)$/si; # untaint |
| | 193 | # Preparing the same statement over & over is wasteful. Granted, |
| | 194 | # performance doesn't really matter in this application, but there is no |
| | 195 | # sense in wasting db resources (which COULD be at a premium). |
| | 196 | |
| | 197 | my %report_statements; |
| | 198 | while (my($element, $sort) = each(%sort)) { |
| | 199 | next if exists $report_statements{$sort}; |
| | 200 | |
| | 201 | $query = <<"endSQL;"; |
| | 202 | SELECT mmr.token, mm.received_date, mm.score, |
| | 203 | mm.sender_email, mm.subject |
| | 204 | FROM maia_mail AS mm, maia_mail_recipients AS mmr |
| | 205 | WHERE mm.id = mmr.mail_id |
| | 206 | AND mmr.type = ? |
| | 207 | AND mmr.recipient_id = ? |
| | 208 | ORDER BY mm.$sort |
| | 209 | endSQL; |
| | 210 | |
| | 211 | $report_statements{$sort} = $dbh->prepare($query) |
| | 212 | or die (sprintf("Maia: [send-quarantine-digests] Couldn't prepare query: %s", $dbh->errstr)); |
| | 213 | } |
| | 214 | |
| | 215 | $query = <<"endSQL;"; |
| | 216 | UPDATE maia_users SET last_digest_sent = ? WHERE id = ? |
| | 217 | endSQL; |
| | 218 | my $update_sth = $dbh->prepare($query) |
| | 219 | or die (sprintf("Maia: [send-quarantine-digests] Couldn't prepare query: %s", $dbh->errstr)); |
| | 220 | |
| | 221 | my $date_add = $isPg ? "NOW() + INTERVAL ? DAY" |
| | 222 | : "DATE_ADD(NOW(), INTERVAL ? DAY)"; |
| | 223 | $query = <<"endSQL;"; |
| | 224 | INSERT INTO maia_tokens (token_system, token, data, expires) |
| | 225 | VALUES ('digest', ?, ?, $date_add) |
| | 226 | endSQL; |
| | 227 | |
| | 228 | my $confirm_sth = $dbh->prepare($query); |
| | 229 | |
| | 230 | while (my @row3 = $users_sth->fetchrow_array()) { |
| | 231 | my $user_id = $1 if $row3[0] =~ /^(\d+)$/si; # untaint |
| | 232 | my $user_email = $1 if $row3[1] =~ /^(.+@.+\..+)$/si; # untaint |
| 286 | | $select = "SELECT maia_mail_recipients.token, maia_mail.received_date, maia_mail.score, " . |
| 287 | | "maia_mail.sender_email, maia_mail.subject " . |
| 288 | | "FROM maia_mail, maia_mail_recipients " . |
| 289 | | "WHERE maia_mail.id = maia_mail_recipients.mail_id " . |
| 290 | | "AND maia_mail_recipients.type = '$report_type{$report_element}' " . |
| 291 | | "AND maia_mail_recipients.recipient_id = ? " . |
| 292 | | "ORDER BY maia_mail.$sort{$report_element}"; |
| 293 | | |
| 294 | | $sth = $dbh->prepare($select) |
| 295 | | or die (sprintf("Maia: [send-quarantine-digests] Couldn't prepare query: %s", $dbh->errstr)); |
| 296 | | $sth->execute($user_id) |
| | 257 | $sth->execute($report_type{$report_element}, $user_id) |
| 302 | | $token = $1 if $row[0] =~ /^([a-zA-Z0-9]+)$/si; # untaint |
| 303 | | $received_date = $1 if $row[1] =~ /^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})$/si; # untaint |
| 304 | | $score = $1 if $row[2] =~ /^(-?\d+\.\d+)$/si; # untaint |
| 305 | | $sender = $1 if $row[3] =~ /^(.+\@.+\..+)$/si; # untaint |
| 306 | | $subject = $1 if $row[4] =~ /^(.*)$/si; # untaint |
| | 263 | my $token = $1 if $row[0] =~ /^([a-zA-Z0-9]+)$/si; # untaint |
| | 264 | my $received_date = $1 if $row[1] =~ /^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})$/si; # untaint |
| | 265 | my $score = $1 if $row[2] =~ /^(-?\d+\.\d+)$/si; # untaint |
| | 266 | my $sender = $1 if $row[3] =~ /^(.+\@.+\..+)$/si; # untaint |
| | 267 | my $subject = $1 if $row[4] =~ /^(.*)$/si; # untaint |
| | 324 | |
| | 325 | # Retrieve the string value associated with a key in the database.cfg file. |
| | 326 | sub get_string_key($$) { |
| | 327 | my ($file, $key) = @_; |
| | 328 | |
| | 329 | if ($file =~ /\n[ \t]*$key[ \t]*=[ \t]*\"(.*)\"/) { |
| | 330 | return ($1); |
| | 331 | } else { |
| | 332 | die ("Maia: [get_db_string_key] Unable to find $key value in $file\n"); |
| | 333 | } |
| | 334 | } |
| | 335 | |
| | 336 | # Read a single value from Maia's configuration table. |
| | 337 | sub get_config_value($$) { |
| | 338 | my($dbh, $key) = @_; |
| | 339 | my($sth, @row, $select); |
| | 340 | my $value = undef; |
| | 341 | |
| | 342 | return $config_value_cache{$key} if (exists $config_value_cache{$key}); |
| | 343 | |
| | 344 | $select = "SELECT " . $key . " FROM maia_config WHERE id = 0"; |
| | 345 | $select = $1 if $select =~ /^(.*)$/si; # untaint |
| | 346 | $sth = $dbh->prepare($select) |
| | 347 | or die (sprintf("Maia: [get_config_value] Couldn't prepare query: %s", $dbh->errstr)); |
| | 348 | $sth->execute() |
| | 349 | or die (sprintf("Maia: [get_config_value] Couldn't execute query: %s", $dbh->errstr)); |
| | 350 | if (@row = $sth->fetchrow_array()) { |
| | 351 | $value = $row[0]; |
| | 352 | } |
| | 353 | $sth->finish; |
| | 354 | $config_value_cache{$key} = $value; |
| | 355 | return $value; |
| | 356 | } |
| | 357 | |
| | 358 | #random phrase generated from password generator |
| | 359 | #credit: http://web.uconn.edu/~cdavid/cgi-bin/book/make_password_html.pl |
| | 360 | sub phrase_generate() { |
| | 361 | my $ug = new Data::UUID; |
| | 362 | my $uuid = $ug->create_hex(); |
| | 363 | $uuid =~ s/0x(.*)/$1/; |
| | 364 | |
| | 365 | my (@passset,$rnd_passwd,$randum_num); |
| | 366 | @passset = ('A'..'Z','0'..'9'); |
| | 367 | $rnd_passwd = ""; |
| | 368 | for (my $i = 0; $i<32;$i++) { |
| | 369 | $randum_num = int(rand($#passset+1)); |
| | 370 | $rnd_passwd .= $passset[$randum_num]; |
| | 371 | } |
| | 372 | |
| | 373 | return $uuid . $rnd_passwd ; |
| | 374 | } |
| | 375 | |
| | 376 | sub generate_confirm_token($$) { |
| | 377 | my ($dbh, $maia_user_id) = @_; |
| | 378 | my $spamexpiry = get_config_value($dbh, "expiry_period"); |
| | 379 | my $hamexpiry = get_config_value($dbh, "ham_cache_expiry_period"); |
| | 380 | my $days = $spamexpiry > $hamexpiry ? $spamexpiry : $hamexpiry; |
| | 381 | |
| | 382 | my $unique_string = phrase_generate(); |
| | 383 | |
| | 384 | $confirm_sth->execute($unique_string, $maia_user_id,$days) or die (sprintf("Maia: [send-quarantine-reminders] Couldn't execute query: %s", $dbh->errstr));; |
| | 385 | $confirm_sth->finish(); |
| | 386 | return $unique_string; |
| | 387 | } |