File: //usr/share/usermin/mailbox/index.cgi
#!/usr/bin/perl
# index.cgi
# List the mail messages for the user
use strict;
use warnings;
no warnings 'redefine';
no warnings 'uninitialized';
our (%text, %in, %userconfig, %config);
our ($remote_user, $remote_pass);
our $special_folder_id;
our $plen;
our ($cb); # XXX
our $search_folder_id;
require './mailbox-lib.pl';
&ReadParse();
&open_dsn_hash();
my @folders = &list_folders_sorted();
if (defined($in{'id'})) {
# Folder ID specified .. convert to index
my $idf = &find_named_folder($in{'id'}, \@folders);
$in{'folder'} = $idf->{'index'} if ($idf);
}
elsif (!defined($in{'folder'}) && $userconfig{'default_folder'}) {
# No folder specified .. find the default by preferences
my $df = &find_named_folder($userconfig{'default_folder'}, \@folders);
$in{'folder'} = $df->{'index'} if ($df);
}
# Get the folder by index
if (!defined($in{'folder'})) {
$in{'folder'} = 0;
}
my ($folder) = grep { $_->{'index'} == $in{'folder'} } @folders;
# Show page header
print "Refresh: $userconfig{'refresh'}\r\n"
if ($userconfig{'refresh'});
my ($qtotal, $qcount, $totalquota, $countquota) = &get_user_quota();
my @topright;
if ($totalquota) {
push(@topright, &text('mail_quota', &nice_size($qtotal),
&nice_size($totalquota)));
}
if (($folder->{'type'} == 2 || $folder->{'type'} == 4) &&
$folder->{'mode'} == 3 && defined($folder->{'user'}) &&
!$folder->{'autouser'} && !$folder->{'nologout'}) {
push(@topright, "<a href='inbox_logout.cgi?folder=$folder->{'index'}'>".
($folder->{'type'} == 2 ? $text{'mail_logout'}
: $text{'mail_logout2'}).
"</a>");
}
# Check if this is a POP3 or IMAP inbox with no login set
if (($folder->{'type'} == 2 || $folder->{'type'} == 4) &&
$folder->{'mode'} == 3 && !$folder->{'autouser'} && !$folder->{'user'}) {
&ui_print_header(undef, &text('index_title', &html_escape($folder->{'name'})), "",
undef, 1, 1, 0, join("<br>", @topright));
print &ui_form_start("inbox_login.cgi", "post");
print &ui_hidden("folder", $folder->{'index'}),"\n";
print &ui_table_start(
$folder->{'type'} == 2 ? $text{'mail_loginheader'}
: $text{'mail_loginheader2'}, undef, 2);
print &ui_table_row(undef, &text('mail_logindesc',
"<tt>$folder->{'server'}</tt>"), 2);
print &ui_table_row($text{'mail_loginuser'},
&ui_textbox("user", $remote_user, 30));
print &ui_table_row($text{'mail_loginpass'},
&ui_password("pass", $remote_pass, 30));
print &ui_table_end();
print &ui_form_end([ [ "login", $text{'mail_login'} ] ]);
&ui_print_footer("/", $text{'index'});
exit;
}
# Work out start from jump page
my $perpage = $folder->{'perpage'} || $userconfig{'perpage'} || 20;
if ($in{'jump'} =~ /^\d+$/ && $in{'jump'} > 0) {
$in{'start'} = ($in{'jump'}-1)*$perpage;
}
# Get email to show, in order
my @error;
my @mail = &mailbox_list_mails_sorted(
int($in{'start'}), int($in{'start'})+$perpage-1,
$folder, !$userconfig{'show_body'}, \@error);
if ($in{'start'} >= @mail && $in{'jump'}) {
# Jumped too far!
$in{'start'} = @mail - $perpage;
@mail = &mailbox_list_mails_sorted(int($in{'start'}),
int($in{'start'})+$perpage-1,
$folder, !$userconfig{'show_body'},
\@error);
}
# Show page title
&ui_print_header(undef, &text('index_title', &html_escape($folder->{'name'})), "", undef,
1, 1, 0, join("<br>", @topright));
# Get folder-selection HTML
my $sel = &folder_select(\@folders, $folder, "id", undef, 1, 1);
# Show page flipping arrows
&show_arrows();
# If this is the search results folder, check if a search is in progress
if ($folder->{'id'} eq $search_folder_id) {
my ($pid, $action) = &test_lock_folder($folder);
if ($pid) {
if ($action && $action->{'search'}) {
print "<b>",&text('index_searching',
"<i>".&html_escape($action->{'search'})."</i>"),
"</b><p>\n";
}
else {
print "<b>",&text('index_searching2'),"</b><p>\n";
}
}
}
# Work out displayed range
my $start = int($in{'start'});
my $end = $in{'start'}+$perpage-1;
$end = scalar(@mail)-1 if ($end >= scalar(@mail));
# Start of form
print &ui_form_start("delete_mail.cgi", "post");
print &ui_hidden("folder", $folder->{'index'});
print &ui_hidden("mod", &modification_time($folder));
print &ui_hidden("start", $in{'start'});
if (@error) {
print "<center><b><font color=#ff0000>\n";
print &text('mail_err', $error[0] == 0 ? $error[1] :
&text('save_elogin', $error[1])),"\n";
print "</font></b></center>\n";
}
# Buttons at top
my @links;
if ($userconfig{'top_buttons'} && @mail) {
&show_mailbox_buttons(1, \@folders, $folder, \@mail);
@links = ( &select_all_link("d", 1),
&select_invert_link("d", 1),
&select_status_link("d", 1, $folder, \@mail, $start, $end,
1, $text{'mail_selread'}),
&select_status_link("d", 1, $folder, \@mail, $start, $end,
0, $text{'mail_selunread'}),
&select_status_link("d", 1, $folder, \@mail, $start, $end,
2, $text{'mail_selspecial'}),
);
my ($sortfield, $sortdir) = &get_sort_field($folder);
if ($sortfield) {
# Show un-sort link
push(@links, "<a href='sort.cgi?folder=$folder->{'index'}&start=$start'>$text{'mail_nosort'}</a>");
}
print &ui_links_row(\@links);
}
# Generate mail list headers
my $showto = $folder->{'show_to'};
my $showfrom = $folder->{'show_from'};
my @tds;
if (@mail) {
my @cols = ( "" );
@tds = ( "width=15" );
if ($showfrom) {
push(@cols, &field_sort_link($text{'mail_from'}, "from",
$folder, $in{'start'}));
push(@tds, "");
}
if ($showto) {
push(@cols, &field_sort_link($text{'mail_to'}, "to",
$folder, $in{'start'}));
push(@tds, "");
}
push(@cols, &field_sort_link($text{'mail_date'}, "date",
$folder, $in{'start'}));
push(@tds, "nowrap");
push(@cols, &field_sort_link($text{'mail_size'}, "size",
$folder, $in{'start'}));
push(@tds, "nowrap");
if ($folder->{'spam'}) {
push(@cols, &field_sort_link($text{'mail_level'},
"x-spam-status", $folder, $in{'start'}));
push(@tds, "");
}
push(@cols, &field_sort_link($text{'mail_subject'}, "subject",
$folder, $in{'start'}));
push(@tds, "");
print &ui_columns_start(\@cols, 100, 0, \@tds);
}
# Pre-check for attachments for the whole list
&mail_has_attachments([ map { $mail[$_] } ($start .. $end) ], $folder);
# Show the actual email
for(my $i=$start; $i<=$end; $i++) {
my ($bs, $be);
my @rowtds = @tds;
my $m = $mail[$i];
my $mid = $m->{'header'}->{'message-id'};
my $r = &get_mail_read($folder, $m);
if ($r&2) {
# Special
($bs, $be) = ("<b><i>", "</i></b>");
}
elsif (($r&1) == 0) {
# Unread
($bs, $be) = ("<b>", "</b>");
}
else {
$bs = $be = "";
}
my $idx = $m->{'idx'};
my $id = $m->{'id'};
my @cols;
# From and To columns, with links
if ($showfrom) {
push(@cols, $bs.&view_mail_link($folder, $id, $in{'start'},
$m->{'header'}->{'from'}).$be);
}
if ($showto) {
push(@cols, $bs.&view_mail_link($folder, $id, $in{'start'},
$m->{'header'}->{'to'}).$be);
}
# Date and size columns
push(@cols, $bs.&simplify_date($m->{'header'}->{'date'}).$be);
push(@cols, $bs.&nice_size($m->{'size'}, 1024).$be);
$rowtds[$#cols] .= " data-sort=".$m->{'size'};
# Spam score
if ($folder->{'spam'}) {
if ($m->{'header'}->{'x-spam-status'} =~ /(hits|score)=([0-9\.]+)/) {
push(@cols, $bs.$2.$be);
}
else {
push(@cols, "");
}
}
# Subject column, with read/special icons
my @icons = &message_icons($m, $folder->{'sent'}, $folder);
push(@cols, $bs.&simplify_subject($m->{'header'}->{'subject'}).
" ".join(" ", @icons).$be);
# Detect IMAP deleted mail
if ($m->{'deleted'}) {
foreach my $c (@cols) {
$c = "<strike>$c</strike>";
}
}
if (&editable_mail($m)) {
print &ui_checked_columns_row(\@cols, \@rowtds, "d", $id);
}
else {
print &ui_columns_row([ "", @cols ], \@rowtds);
}
&update_delivery_notification($mail[$i], $folder);
# Show part of the body too
if ($userconfig{'show_body'}) {
$plen = $in{'show_body_len'} || $userconfig{'show_body_len'};
&parse_mail($m);
my $data = &mail_preview($m, $plen);
if ($data) {
print "<tr $cb> <td colspan=",(scalar(@cols)+1),"><tt>",
&html_escape($data),"</tt></td> </tr>\n";
}
}
}
if (@mail) {
print &ui_columns_end();
print &ui_links_row(\@links);
}
# Buttons at end of form
&show_mailbox_buttons(2, \@folders, $folder, \@mail);
print &ui_form_end();
if ($userconfig{'arrows'}) {
# Show page flipping arrows
print "<br>\n";
&show_arrows();
}
# Start section for end of page buttons, in a 3-wide grid
print "<hr>\n";
my @grid;
print "<table width=100%>\n";
if (@mail) {
my $jumpform = (@mail > $perpage);
if ($folder->{'searchable'}) {
# Simple search
my $ssform = &ui_form_start("mail_search.cgi");
$ssform .= &ui_hidden("folder", $folder->{'index'});
$ssform .= &ui_hidden("simple", 1);
$ssform .= &ui_submit($text{'mail_search2'});
$ssform .= &ui_textbox("search", undef, 20);
$ssform .= &ui_form_end();
push(@grid, $ssform);
# Advanced search
push(@grid, &ui_form_start("search_form.cgi").
&ui_hidden("folder", $folder->{'index'}).
&ui_submit($text{'mail_advanced'}, "advanced").
&ui_form_end());
}
if ($folder->{'spam'} && $folder->{'searchable'}) {
# Spam level search
push(@grid, &ui_form_start("mail_search.cgi").
&ui_hidden("folder", $folder->{'index'}).
&ui_hidden("spam", 1).
&ui_submit($text{'mail_search3'}).
&ui_textbox("score", undef, 5).
&ui_form_end());
}
if ($jumpform) {
# Show page jump form
push(@grid, &ui_form_start("index.cgi").
&ui_hidden("folder", $folder->{'index'}).
&ui_submit($text{'mail_jump'}).
&ui_textbox("jump",
int(int($in{'start'}) / $perpage)+1,
3)." $text{'mail_of'} ".
(int(@mail / $perpage)+1).
&ui_form_end());
}
}
# Address book button
no warnings "once";
if (!$main::mailbox_no_addressbook_button) {
push(@grid, &ui_form_start("list_addresses.cgi").
&ui_submit($text{'mail_addresses'}).
&ui_form_end());
}
# Folder management button
if (!$main::mailbox_no_folder_button) {
push(@grid, &ui_form_start($config{'mail_system'} == 4 ?
"list_ifolders.cgi" : "list_folders.cgi").
&ui_submit($text{'mail_folders'}).
&ui_form_end());
}
use warnings "once";
# Sig editor
push(@grid, &ui_form_start("edit_sig.cgi").
&ui_submit($text{'mail_sig'}).
&ui_form_end());
# Show button to delete all mail in folder
if (@mail && ($folder->{'trash'} || $userconfig{'show_delall'})) {
push(@grid, &ui_form_start("delete_mail.cgi").
&ui_hidden("folder", $folder->{'index'}).
&ui_hidden("all", 1).
&ui_submit($folder->{'trash'} ? $text{'mail_deltrash'}
: $text{'mail_delall'},
"delete").
&ui_form_end());
}
# Show special sync button
if ($folder->{'type'} == 6 && $folder->{'id'} == $special_folder_id) {
push(@grid, &ui_form_start("specialsync.cgi").
&ui_submit($text{'mail_specialsync'}).
&ui_form_end());
}
print &ui_grid_table(\@grid, 3, 100,
[ "align=left width=33%", "align=center width=33%", "align=right width=33%" ],
"cellpadding=0 cellspacing=0");
if ($in{'refresh'}) {
# Previous CGI has asked for a theme refresh, due to read counts
# possibly changing or a folder being added
if (defined(&theme_post_save_folder)) {
&theme_post_save_folder($folder,
$in{'refresh'} == 2 ? 'create' : 'read');
}
}
&save_last_folder_id($folder);
&ui_print_footer("/", $text{'index'});
&pop3_logout();
# show_arrows()
# Prints HTML for previous/next page arrows
sub show_arrows
{
my $link = "index.cgi?folder=".$in{'folder'};
my $left = $in{'start'} ?
$link."&start=".($in{'start'}-$perpage) : undef;
my $right = int($in{'start'})+$perpage < @mail ?
$link."&start=".($in{'start'}+$perpage) : undef;
my $first = $in{'start'} ?
$link."&start=0" : undef;
my $last = int($in{'start'})+$perpage < @mail ?
$link."&start=".(int((scalar(@mail)-$perpage-1)/$perpage + 1)*$perpage) : undef;
my $s = @mail-$in{'start'};
my $e = @mail-$in{'start'}-$perpage+1;
print &ui_page_flipper(
@mail ? &text('mail_pos', $e < 1 ? 1 : $e, $s, scalar(@mail), $sel)
: &text('mail_none', $sel),
&ui_submit($text{'mail_fchange'}).&ui_hidden("user", $in{'user'}),
"index.cgi",
$left,
$right,
$first,
$last,
$folder->{'msg'},
);
}