Sharedwww / cgi-bin / openwebmail / openwebmail-main.plOpen in CoCalc
Author: William A. Stein
1
#!/usr/bin/suidperl -T
2
#
3
# openwebmail-main.pl - message list browsing program
4
#
5
6
use vars qw($SCRIPT_DIR);
7
if ( $0 =~ m!^(\S*)/[\w\d\-\.]+\.pl! ) { $SCRIPT_DIR=$1 }
8
if ($SCRIPT_DIR eq '' && open(F, '/etc/openwebmail/openwebmail_path.conf')) {
9
$_=<F>; close(F); if ( $_=~/^(\S*)/) { $SCRIPT_DIR=$1 }
10
}
11
if ($SCRIPT_DIR eq '') { print "Content-type: text/html\n\nSCRIPT_DIR not set in /etc/openwebmail/openwebmail_path.conf !\n"; exit 0; }
12
push (@INC, $SCRIPT_DIR);
13
14
foreach (qw(ENV BASH_ENV CDPATH IFS TERM)) {delete $ENV{$_}}; $ENV{PATH}='/bin:/usr/bin'; # secure ENV
15
umask(0002); # make sure the openwebmail group can write
16
17
use strict;
18
use Fcntl qw(:DEFAULT :flock);
19
use CGI qw(-private_tempfiles :standard);
20
use CGI::Carp qw(fatalsToBrowser carpout);
21
22
require "modules/dbm.pl";
23
require "modules/suid.pl";
24
require "modules/filelock.pl";
25
require "modules/tool.pl";
26
require "modules/datetime.pl";
27
require "modules/lang.pl";
28
require "modules/htmltext.pl";
29
require "modules/mime.pl";
30
require "modules/mailparse.pl";
31
require "modules/spamcheck.pl";
32
require "modules/viruscheck.pl";
33
require "auth/auth.pl";
34
require "quota/quota.pl";
35
require "shares/ow-shared.pl";
36
require "shares/iconv.pl";
37
require "shares/maildb.pl";
38
require "shares/lockget.pl";
39
require "shares/cut.pl";
40
require "shares/getmsgids.pl";
41
require "shares/fetchmail.pl";
42
require "shares/pop3book.pl";
43
require "shares/calbook.pl";
44
require "shares/mailfilter.pl";
45
46
# common globals
47
use vars qw(%config %config_raw);
48
use vars qw($thissession);
49
use vars qw($default_logindomain);
50
use vars qw($domain $user $userrealname $uuid $ugid $homedir);
51
use vars qw(%prefs %style %icontext);
52
use vars qw($quotausage $quotalimit);
53
54
# extern vars
55
use vars qw(%lang_folders %lang_sizes %lang_text %lang_err %lang_sortlabels
56
%lang_calendar %lang_wday); # defined in lang/xy
57
use vars qw($_STATUS); # defined in maildb.pl
58
59
# local globals
60
use vars qw($folder);
61
use vars qw($sort $page $longpage);
62
use vars qw($searchtype $keyword);
63
use vars qw($escapedfolder $escapedkeyword);
64
65
########## MAIN ##################################################
66
openwebmail_requestbegin();
67
$SIG{PIPE}=\&openwebmail_exit; # for user stop
68
$SIG{TERM}=\&openwebmail_exit; # for user stop
69
$SIG{CHLD}='IGNORE'; # prevent zombie
70
71
userenv_init();
72
73
my $action = param('action')||'';
74
if (!$config{'enable_webmail'} && $action ne "logout") {
75
openwebmailerror(__FILE__, __LINE__, "$lang_text{'webmail'} $lang_err{'access_denied'}");
76
}
77
78
$folder = param('folder') || 'INBOX';
79
$page = param('page') || 1;
80
$longpage = param('longpage') || 0;
81
$sort = param('sort') || $prefs{'sort'} || 'date';
82
$searchtype = param('searchtype') || 'subject';
83
$keyword = param('keyword') || ''; $keyword=~s/^\s*//; $keyword=~s/\s*$//;
84
85
$escapedfolder = ow::tool::escapeURL($folder);
86
$escapedkeyword = ow::tool::escapeURL($keyword);
87
88
if ($action eq "movemessage" ||
89
defined(param('movebutton')) ||
90
defined(param('copybutton')) ) {
91
my @messageids = param('message_ids');
92
my $destination = ow::tool::untaint(safefoldername(param('destination')));
93
if ($destination eq 'FORWARD' && $#messageids>=0) { # forwarding msgs
94
open (FORWARDIDS, ">$config{'ow_sessionsdir'}/$thissession-forwardids");
95
print FORWARDIDS join("\n", @messageids);
96
close(FORWARDIDS);
97
my $send_url = qq|$config{'ow_cgiurl'}/openwebmail-send.pl?|.
98
qq|sessionid=$thissession&amp;folder=$escapedfolder&amp;|.
99
qq|page=$page&amp;longpage=$longpage&amp;|.
100
qq|sort=$sort&amp;keyword=$escapedkeyword&amp;searchtype=$searchtype&amp;|.
101
qq|compose_caller=main&amp;action=composemessage|;
102
if (defined(param('movebutton'))) {
103
print redirect(-location=>"$send_url&amp;composetype=forwardids_delete");
104
} else {
105
print redirect(-location=>"$send_url&amp;composetype=forwardids");
106
}
107
} else { # move/copy/del msgs
108
movemessage(\@messageids, $destination) if ($#messageids>=0);
109
if (param('messageaftermove')) {
110
my $headers = param('headers') || $prefs{'headers'} || 'simple';
111
my $attmode = param('attmode') || 'simple';
112
my $escapedmessageid=ow::tool::escapeURL(param('message_id')||'');
113
$escapedmessageid=ow::tool::escapeURL($messageids[0]) if (defined(param('copybutton'))); # copy button pressed, msg not moved
114
print redirect(-location=>"$config{'ow_cgiurl'}/openwebmail-read.pl?sessionid=$thissession&folder=$escapedfolder&page=$page&longpage=$longpage&sort=$sort&keyword=$escapedkeyword&searchtype=$searchtype&message_id=$escapedmessageid&action=readmessage&headers=$headers&attmode=$attmode");
115
} else {
116
listmessages();
117
}
118
}
119
} elsif ($action eq "listmessages_afterlogin") {
120
clean_trash_spamvirus();
121
if ($quotalimit>0 && $quotausage>$quotalimit) {
122
$quotausage=(ow::quota::get_usage_limit(\%config, $user, $homedir, 1))[2];
123
}
124
if ( ($config{'forced_moveoldmsgfrominbox'}||$prefs{'moveoldmsgfrominbox'}) &&
125
(!$quotalimit||$quotausage<$quotalimit) ) {
126
moveoldmsg2saved();
127
}
128
update_pop3check();
129
authpop3_fetch() if ($config{'auth_module'} eq 'auth_pop3.pl' ||
130
$config{'auth_module'} eq 'auth_ldap_vpopmail.pl');
131
pop3_fetches($prefs{'autopop3wait'}) if ($config{'enable_pop3'} && $prefs{'autopop3'});
132
listmessages();
133
} elsif ($action eq "userrefresh") {
134
if ($folder eq 'INBOX') {
135
authpop3_fetch() if ($config{'auth_module'} eq 'auth_pop3.pl' ||
136
$config{'auth_module'} eq 'auth_ldap_vpopmail.pl');
137
}
138
if ($config{'quota_module'} ne 'none') {
139
$quotausage=(ow::quota::get_usage_limit(\%config, $user, $homedir, 1))[2];
140
}
141
listmessages();
142
if (update_pop3check()) {
143
pop3_fetches(0) if ($config{'enable_pop3'} && $prefs{'autopop3'});
144
}
145
} elsif ($action eq "listmessages") {
146
my $update=0; $update=1 if (update_pop3check());
147
if ($update) { # get mail from auth pop3 server
148
authpop3_fetch() if ($config{'auth_module'} eq 'auth_pop3.pl' ||
149
$config{'auth_module'} eq 'auth_ldap_vpopmail.pl');
150
}
151
listmessages();
152
if ($update) { # get mail from misc pop3 servers
153
pop3_fetches(0) if ($config{'enable_pop3'} && $prefs{'autopop3'});
154
}
155
} elsif ($action eq "markasread") {
156
markasread();
157
listmessages();
158
} elsif ($action eq "markasunread") {
159
markasunread();
160
listmessages();
161
} elsif ($action eq "pop3fetches" && $config{'enable_pop3'}) {
162
www_pop3_fetches();
163
listmessages();
164
} elsif ($action eq "pop3fetch" && $config{'enable_pop3'}) {
165
www_pop3_fetch();
166
listmessages();
167
} elsif ($action eq "emptyfolder") {
168
www_emptyfolder($folder);
169
if ($quotalimit>0 && $quotausage>$quotalimit) {
170
$quotausage=(ow::quota::get_usage_limit(\%config, $user, $homedir, 1))[2];
171
}
172
listmessages();
173
} elsif ($action eq "logout") {
174
clean_trash_spamvirus();
175
if ( ($config{'forced_moveoldmsgfrominbox'}||
176
$prefs{'moveoldmsgfrominbox'}) &&
177
(!$quotalimit||$quotausage<$quotalimit) ) {
178
moveoldmsg2saved();
179
}
180
logout();
181
} else {
182
openwebmailerror(__FILE__, __LINE__, "Action $lang_err{'has_illegal_chars'}");
183
}
184
185
openwebmail_requestend();
186
########## END MAIN ##############################################
187
188
########## LISTMESSGAES ##########################################
189
sub listmessages {
190
my $orig_inbox_newmessages=0;
191
my $now_inbox_newmessages=0;
192
my $now_inbox_allmessages=0;
193
my $inboxsize_k=0;
194
my $folder_allmessages=0;
195
my %FDB;
196
197
my $spooldb=(get_folderpath_folderdb($user, 'INBOX'))[1];
198
if (ow::dbm::exist($spooldb)) {
199
ow::dbm::open(\%FDB, $spooldb, LOCK_SH) or
200
openwebmailerror(__FILE__, __LINE__, "$lang_err{'couldnt_locksh'} db $spooldb");
201
$orig_inbox_newmessages=$FDB{'NEWMESSAGES'}; # new msg in INBOX
202
ow::dbm::close(\%FDB, $spooldb);
203
}
204
205
# filtermessage in background
206
filtermessage($user, 'INBOX', \%prefs);
207
208
my (@validfolders, $inboxusage, $folderusage);
209
getfolders(\@validfolders, \$inboxusage, \$folderusage);
210
211
my $quotahit_deltype='';
212
if ($quotalimit>0 && $quotausage>$quotalimit &&
213
($config{'delmail_ifquotahit'}||$config{'delfile_ifquotahit'}) ) {
214
$quotausage=(ow::quota::get_usage_limit(\%config, $user, $homedir, 1))[2]; # get uptodate usage
215
if ($quotausage>$quotalimit) {
216
if ($config{'delmail_ifquotahit'} && $folderusage > $quotausage*0.5) {
217
$quotahit_deltype='quotahit_delmail';
218
cutfoldermails(($quotausage-$quotalimit*0.9)*1024, $user, @validfolders);
219
} elsif ($config{'delfile_ifquotahit'}) {
220
$quotahit_deltype='quotahit_delfile';
221
my $webdiskrootdir=$homedir.absolute_vpath("/", $config{'webdisk_rootpath'});
222
cutdirfiles(($quotausage-$quotalimit*0.9)*1024, $webdiskrootdir);
223
}
224
$quotausage=(ow::quota::get_usage_limit(\%config, $user, $homedir, 1))[2]; # get uptodate usage
225
}
226
}
227
228
# reset global $folder to INBOX if it is not a valid folder
229
my $is_validfolder=0;
230
foreach (@validfolders) {
231
if ($_ eq $folder) { $is_validfolder=1; last; }
232
}
233
$folder='INBOX' if (!$is_validfolder);
234
235
my ($totalsize, $newmessages, $r_messageids, $r_messagedepths)=getinfomessageids($user, $folder, $sort, $searchtype, $keyword);
236
237
my $msgsperpage=$prefs{'msgsperpage'}||10; $msgsperpage=1000 if ($longpage);
238
my $totalmessage=$#{$r_messageids}+1; $totalmessage=0 if ($totalmessage<0);
239
my $totalpage=int($totalmessage/$msgsperpage+0.999999); $totalpage=1 if ($totalpage==0);
240
241
$page = 1 if ($page < 1); $page = $totalpage if ($page>$totalpage);
242
243
my $firstmessage = ($page-1)*$msgsperpage + 1;
244
my $lastmessage = $firstmessage + $msgsperpage - 1;
245
$lastmessage = $totalmessage if ($lastmessage>$totalmessage);
246
247
my $main_url = "$config{'ow_cgiurl'}/openwebmail-main.pl?sessionid=$thissession&amp;sort=$sort&amp;folder=$escapedfolder";
248
my $main_url_with_keyword = "$main_url&amp;keyword=$escapedkeyword&amp;searchtype=$searchtype";
249
250
my ($html, $temphtml);
251
$html = applystyle(readtemplate("viewfolder.template"));
252
253
$temphtml = end_form();
254
$html =~ s/\@\@\@ENDFORM\@\@\@/$temphtml/g;
255
256
### we don't keep keyword, firstpage between folders,
257
### thus the keyword, firstpage will be cleared when user change folder
258
$temphtml = startform(-action=>"$config{'ow_cgiurl'}/openwebmail-main.pl",
259
-name=>'FolderForm').
260
ow::tool::hiddens(sessionid=>$thissession,
261
sort=>$sort,
262
action=>'listmessages');
263
$html =~ s/\@\@\@STARTFOLDERFORM\@\@\@/$temphtml/;
264
265
# this popup_menu is done with pure html code
266
# because we want to set font style for options in the select menu
267
my $select_str=qq|\n<SELECT name="folder" accesskey="L" onChange="JavaScript:document.FolderForm.submit();">\n|;
268
269
foreach my $foldername (@validfolders) {
270
my ($folderfile, $folderdb, $newmessages, $allmessages);
271
272
# find message count for folderlabel
273
($folderfile, $folderdb)=get_folderpath_folderdb($user, $foldername);
274
if (ow::dbm::exist($folderdb)) {
275
ow::dbm::open(\%FDB, $folderdb, LOCK_SH) or
276
openwebmailerror(__FILE__, __LINE__, "$lang_err{'couldnt_locksh'} db $folderdb");
277
$allmessages=$FDB{'ALLMESSAGES'}-$FDB{'ZAPMESSAGES'};
278
$allmessages-=$FDB{'INTERNALMESSAGES'} if ($prefs{'hideinternal'});
279
$newmessages=$FDB{'NEWMESSAGES'};
280
if ($foldername eq 'INBOX') {
281
$now_inbox_allmessages=$allmessages;
282
$now_inbox_newmessages=$newmessages;
283
$inboxsize_k=(-s $folderfile)/1024;
284
} elsif ($foldername eq $folder) {
285
$folder_allmessages=$allmessages;
286
}
287
ow::dbm::close(\%FDB, $folderdb);
288
}
289
290
my $option_str=qq|<OPTION value="$foldername"|;
291
$option_str.=qq| selected| if ($foldername eq $folder);
292
if ($newmessages>0) {
293
$option_str.=qq| class="hilighttext">|;
294
} else {
295
$option_str.=qq|>|;
296
}
297
if (defined $lang_folders{$foldername}) {
298
$option_str.=$lang_folders{$foldername};
299
} else {
300
$option_str.=$foldername;
301
}
302
$option_str.=" ($newmessages/$allmessages)" if ( $newmessages ne "" && $allmessages ne "");
303
304
$select_str.="$option_str</OPTION>\n";
305
}
306
$select_str.="</SELECT>\n";
307
308
$temphtml=$select_str;
309
if ( $ENV{'HTTP_USER_AGENT'} =~ /lynx/i || # take care for text browser...
310
$ENV{'HTTP_USER_AGENT'} =~ /w3m/i ) {
311
$temphtml .= submit(-name=>$lang_text{'read'},
312
-class=>"medtext");
313
}
314
$html =~ s/\@\@\@FOLDERPOPUP\@\@\@/$temphtml/;
315
316
if ($config{'quota_module'} ne "none") {
317
$temphtml='';
318
my $overthreshold=($quotalimit>0 && $quotausage/$quotalimit>$config{'quota_threshold'}/100);
319
if ($config{'quota_threshold'}==0 || $overthreshold) {
320
$temphtml = "$lang_text{'quotausage'}: ".lenstr($quotausage*1024,1);
321
}
322
if ($overthreshold) {
323
$temphtml.=" (".(int($quotausage*1000/$quotalimit)/10)."%) ";
324
}
325
} else {
326
$temphtml="&nbsp;";
327
}
328
$html =~ s/\@\@\@QUOTAUSAGE\@\@\@/$temphtml/;
329
330
$temphtml = '';
331
if ($totalmessage>0) {
332
$temphtml .= "$newmessages $lang_text{'unread'} / " if ($newmessages);
333
$temphtml .= "$totalmessage $lang_text{'messages'} / ". lenstr($totalsize, 1);
334
} else {
335
$temphtml = $lang_text{'nomessages'};
336
}
337
$html =~ s/\@\@\@NUMBEROFMESSAGES\@\@\@/$temphtml/;
338
339
# quota or spool over the limit
340
my $limited=(($quotalimit>0 && $quotausage>$quotalimit) || # quota
341
($config{'spool_limit'}>0 && $inboxsize_k>$config{'spool_limit'})); # spool
342
343
$temphtml = '';
344
if (!$limited) {
345
$temphtml .= iconlink("compose.gif", $lang_text{'composenew'}, qq|accesskey="C" href="$config{'ow_cgiurl'}/openwebmail-send.pl?action=composemessage&amp;sessionid=$thissession&amp;sort=$sort&amp;keyword=$escapedkeyword&amp;searchtype=$searchtype&amp;folder=$escapedfolder&amp;page=$page&amp;compose_caller=main"|);
346
$temphtml .= qq|&nbsp;\n|;
347
}
348
349
$temphtml .= iconlink("folder.gif", $lang_text{'folders'}, qq|accesskey="F" href="$config{'ow_cgiurl'}/openwebmail-folder.pl?action=editfolders&amp;sessionid=$thissession&amp;sort=$sort&amp;keyword=$escapedkeyword&amp;searchtype=$searchtype&amp;folder=$escapedfolder&amp;page=$page"|).
350
iconlink("addrbook.gif", $lang_text{'addressbook'}, qq|accesskey="A" href="$config{'ow_cgiurl'}/openwebmail-abook.pl?action=editaddresses&amp;sessionid=$thissession&amp;sort=$sort&amp;keyword=$escapedkeyword&amp;searchtype=$searchtype&amp;folder=$escapedfolder&amp;page=$page"|);
351
if ($config{'enable_userfilter'}) {
352
$temphtml .= iconlink("filtersetup.gif", $lang_text{'filterbook'}, qq|accesskey="I" href="$config{'ow_cgiurl'}/openwebmail-prefs.pl?action=editfilter&amp;sessionid=$thissession&amp;sort=$sort&amp;keyword=$escapedkeyword&amp;searchtype=$searchtype&amp;folder=$escapedfolder&amp;page=$page"|);
353
}
354
355
$temphtml .= qq|&nbsp;\n|;
356
357
if ($config{'enable_pop3'} && $folder eq "INBOX") {
358
$temphtml .= iconlink("pop3.gif", $lang_text{'retr_pop3s'}, qq|accesskey="G" href="$main_url_with_keyword&amp;action=pop3fetches"|);
359
}
360
$temphtml .= iconlink("advsearch.gif", $lang_text{'advsearch'}, qq|accesskey="V" href="$config{'ow_cgiurl'}/openwebmail-advsearch.pl?action=advsearch&amp;sessionid=$thissession&amp;folder=$escapedfolder&amp;page=$page"|);
361
$temphtml .= iconlink("refresh.gif", $lang_text{'refresh'}, qq|accesskey="R" href="$main_url&amp;action=userrefresh&amp;page=$page&amp;userfresh=1"|);
362
363
$temphtml .= qq|&nbsp;\n|;
364
365
if ($config{'enable_calendar'}) {
366
$temphtml .= iconlink("calendar.gif", $lang_text{'calendar'}, qq|accesskey="K" href="$config{'ow_cgiurl'}/openwebmail-cal.pl?action=$prefs{'calendar_defaultview'}&amp;sessionid=$thissession&amp;folder=$escapedfolder"|);
367
}
368
if ($config{'enable_webdisk'}) {
369
$temphtml .= iconlink("webdisk.gif", $lang_text{'webdisk'}, qq|accesskey="E" href="$config{'ow_cgiurl'}/openwebmail-webdisk.pl?action=showdir&amp;sessionid=$thissession&amp;folder=$escapedfolder"|);
370
}
371
if ( $config{'enable_sshterm'}) {
372
if ( -r "$config{'ow_htmldir'}/applet/mindterm2/mindterm.jar" ) {
373
$temphtml .= iconlink("sshterm.gif" ,"$lang_text{'sshterm'} ", qq|accesskey="T" href="#" onClick="window.open('$config{ow_htmlurl}/applet/mindterm2/ssh2.html', '_applet', 'width=400,height=100,top=2000,left=2000,resizable=no,menubar=no,scrollbars=no');"|);
374
} elsif ( -r "$config{'ow_htmldir'}/applet/mindterm/mindtermfull.jar" ) {
375
$temphtml .= iconlink("sshterm.gif" ,"$lang_text{'sshterm'} ", qq|accesskey="T" href="#" onClick="window.open('$config{ow_htmlurl}/applet/mindterm/ssh.html', '_applet', 'width=400,height=100,top=2000,left=2000,resizable=no,menubar=no,scrollbars=no');"|);
376
}
377
}
378
if ( $config{'enable_preference'}) {
379
$temphtml .= iconlink("prefs.gif", $lang_text{'userprefs'}, qq|accesskey="O" href="$config{'ow_cgiurl'}/openwebmail-prefs.pl?action=editprefs&amp;sessionid=$thissession&amp;folder=$escapedfolder&amp;sort=$sort&amp;page=$page&amp;prefs_caller=main"|);
380
}
381
$temphtml .= iconlink("logout.gif", "$lang_text{'logout'} $prefs{'email'}", qq|accesskey="X" href="$main_url&amp;action=logout"|);
382
383
$html =~ s/\@\@\@LEFTMENUBARLINKS\@\@\@/$temphtml/;
384
385
$temphtml='';
386
if ($config{'enable_learnspam'} &&
387
$folder ne 'saved-drafts' && $folder ne 'sent-mail' &&
388
$folder ne 'spam-mail' && $folder ne 'virus-mail') {
389
$temphtml = iconlink("learnspam.gif", $lang_text{'learnspam'}, qq|accesskey="Z" href="JavaScript:document.pageform.destination.value='LEARNSPAM'; document.pageform.movebutton.click();"|);
390
}
391
if ($folder eq 'mail-trash' || $folder eq 'spam-mail' || $folder eq 'virus-mail') {
392
$temphtml .= iconlink("emptyfolder.gif", $lang_text{'emptyfolder'}, qq|accesskey="Z" href="$main_url_with_keyword&amp;action=emptyfolder&amp;page=$page&amp;longpage=$longpage" onclick="return confirm('$lang_text{emptyfolder} ($lang_folders{$folder}, $folder_allmessages $lang_text{messages}) ?');"|);
393
} else {
394
my $trashfolder='mail-trash';
395
$trashfolder='DELETE' if ($quotalimit>0 && $quotausage>$quotalimit);
396
$temphtml .= iconlink("totrash.gif", $lang_text{'totrash'}, qq|accesskey="Z" href="JavaScript:document.pageform.destination.value='$trashfolder'; document.pageform.movebutton.click();"|);
397
}
398
$temphtml .= qq|&nbsp;\n|;
399
400
$html =~ s/\@\@\@RIGHTMENUBARLINKS\@\@\@/$temphtml/;
401
402
$temphtml = start_form(-action=>"$config{'ow_cgiurl'}/openwebmail-main.pl",
403
-name=> 'pageform').
404
ow::tool::hiddens(action=>'listmessages',
405
sessionid=>$thissession,
406
sort=>$sort,
407
folder=>$folder);
408
$html =~ s/\@\@\@STARTPAGEFORM\@\@\@/$temphtml/;
409
410
$temphtml="";
411
if ($config{'enable_calendar'} && $prefs{'calendar_reminderdays'}>0) {
412
$temphtml=eventreminder_html($prefs{'calendar_reminderdays'});
413
}
414
if ($temphtml ne "") {
415
$html =~ s/\@\@\@EVENTREMINDER\@\@\@/$temphtml/;
416
} else {
417
$html =~ s/\@\@\@EVENTREMINDER\@\@\@/&nbsp;/;
418
}
419
420
421
my $sort_url="$config{'ow_cgiurl'}/openwebmail-main.pl?action=listmessages&amp;page=$page&amp;longpage=$longpage&amp;longpage=$longpage&amp;sessionid=$thissession&amp;keyword=$escapedkeyword&amp;searchtype=$searchtype&amp;folder=$escapedfolder&amp;sort";
422
my $linetemplate=$prefs{'fieldorder'};
423
$linetemplate=~s/date/\@\@\@DATE\@\@\@/;
424
$linetemplate=~s/from/\@\@\@FROM\@\@\@/;
425
$linetemplate=~s/size/\@\@\@SIZE\@\@\@/;
426
$linetemplate=~s/subject/\@\@\@SUBJECT\@\@\@/;
427
$linetemplate='@@@[email protected]@@ '.$linetemplate.' @@@[email protected]@@';
428
429
my $headershtml='';
430
my $linehtml=$linetemplate;
431
432
$temphtml = iconlink("unread.gif", $lang_sortlabels{'status'}, qq|href="$sort_url=status"|);
433
$temphtml = qq|<td width="6%" bgcolor=$style{'columnheader'} align="center">$temphtml</td>\n|;
434
$linehtml =~ s/\@\@\@STATUS\@\@\@/$temphtml/;
435
436
if ($sort eq "date") {
437
$temphtml = qq|<a href="$sort_url=date_rev">$lang_text{'date'}</a> |.iconlink("up.gif", "^", "");
438
} elsif ($sort eq "date_rev") {
439
$temphtml = qq|<a href="$sort_url=date">$lang_text{'date'}</a> |.iconlink("down.gif", "v", "");;
440
} else {
441
$temphtml = qq|<a href="$sort_url=date">$lang_text{'date'}</a>|;
442
}
443
$temphtml = qq|<td width="22%" bgcolor=$style{'columnheader'}><B>$temphtml</B></td>\n|;
444
$linehtml =~ s/\@\@\@DATE\@\@\@/$temphtml/;
445
446
if ( $folder=~ m#sent-mail#i ||
447
$folder=~ m#saved-drafts#i ||
448
$folder=~ m#\Q$lang_folders{'sent-mail'}\E#i ||
449
$folder=~ m#\Q$lang_folders{'saved-drafts'}\E#i ) {
450
if ($sort eq "recipient") {
451
$temphtml = qq|<a href="$sort_url=recipient_rev">$lang_text{'recipient'}</a> |.iconlink("up.gif", "^", "");
452
} elsif ($sort eq "recipient_rev") {
453
$temphtml = qq|<a href="$sort_url=recipient">$lang_text{'recipient'}</a> |.iconlink("down.gif", "v", "");
454
} else {
455
$temphtml = qq|<a href="$sort_url=recipient">$lang_text{'recipient'}</a>|;
456
}
457
} else {
458
if ($sort eq "sender") {
459
$temphtml = qq|<a href="$sort_url=sender_rev">$lang_text{'sender'}</a> |.iconlink("up.gif", "^", "");
460
} elsif ($sort eq "sender_rev") {
461
$temphtml = qq|<a href="$sort_url=sender">$lang_text{'sender'}</a> |.iconlink("down.gif", "v", "");
462
} else {
463
$temphtml = qq|<a href="$sort_url=sender">$lang_text{'sender'}</a>|;
464
}
465
}
466
$temphtml = qq|<td width="25%" bgcolor=$style{'columnheader'}><B>$temphtml</B></td>\n|;
467
$linehtml =~ s/\@\@\@FROM\@\@\@/$temphtml/;
468
469
if ($sort eq "subject") {
470
$temphtml = qq|<a href="$sort_url=subject_rev">$lang_text{'subject'}</a> |.iconlink("up.gif", "^", "");
471
} elsif ($sort eq "subject_rev") {
472
$temphtml = qq|<a href="$sort_url=subject">$lang_text{'subject'}</a> |.iconlink("down.gif", "v", "");
473
} else {
474
$temphtml = qq|<a href="$sort_url=subject">$lang_text{'subject'}</a>|;
475
}
476
$temphtml = qq|<td bgcolor=$style{'columnheader'}><B>$temphtml</B></td>\n|;
477
$linehtml =~ s/\@\@\@SUBJECT\@\@\@/$temphtml/;
478
479
if ($sort eq "size") {
480
$temphtml = qq|<a href="$sort_url=size_rev">$lang_text{'size'}</a> |.iconlink("up.gif", "^", "");
481
} elsif ($sort eq "size_rev") {
482
$temphtml = qq|<a href="$sort_url=size">$lang_text{'size'}</a> |.iconlink("down.gif", "v", "");
483
} else {
484
if ($folder eq "mail-trash" || $folder eq "spam-mail" || $folder eq "virus-mail") {
485
$temphtml = qq|<a href="$sort_url=size_rev">$lang_text{'size'}</a>|;
486
} else {
487
$temphtml = qq|<a href="$sort_url=size">$lang_text{'size'}</a>|;
488
}
489
}
490
$temphtml = qq|<td width="5%" bgcolor=$style{'columnheader'} align="right"><B>$temphtml</B></td>\n|;
491
$linehtml =~ s/\@\@\@SIZE\@\@\@/$temphtml/;
492
493
$temphtml = qq|<td width="3%" bgcolor=$style{'columnheader'} align ="center">|.
494
checkbox(-name=>'allbox',
495
-value=>'1',
496
-onClick=>"CheckAll($prefs{'uselightbar'});",
497
-label=>'',
498
-override=>'1').
499
qq|</td>\n|;
500
$linehtml =~ s/\@\@\@CHECKBOX\@\@\@/$temphtml/;
501
502
$headershtml .= qq|<tr>$linehtml</tr>\n|;
503
504
my ($folderfile, $folderdb)=get_folderpath_folderdb($user, $folder);
505
my ($messageid, $messagedepth, $escapedmessageid);
506
my ($offset, $from, $to, $dateserial, $subject, $content_type, $status, $messagesize, $references, $charset);
507
my ($tr_bgcolorstr, $td_bgcolorstr, $checkbox_onclickstr, $boldon, $boldoff);
508
509
ow::dbm::open(\%FDB, $folderdb, LOCK_SH) or
510
openwebmailerror(__FILE__, __LINE__, "$lang_err{'couldnt_locksh'} db $folderdb");
511
512
$temphtml = '';
513
foreach my $messnum ($firstmessage .. $lastmessage) {
514
$messageid=${$r_messageids}[$messnum-1];
515
$messagedepth=${$r_messagedepths}[$messnum-1];
516
next if (! defined($FDB{$messageid}) );
517
518
$escapedmessageid = ow::tool::escapeURL($messageid);
519
($offset, $from, $to, $dateserial, $subject,
520
$content_type, $status, $messagesize, $references, $charset)=string2msgattr($FDB{$messageid});
521
if ($charset eq '' && $prefs{'charset'} eq 'utf-8') {
522
# assume msg is from sender using same language as the recipient's browser
523
$charset=$ow::lang::languagecharsets{ow::lang::guess_language()};
524
}
525
526
# convert from mesage charset to current user charset
527
if (is_convertable($charset, $prefs{'charset'})) {
528
($from, $to, $subject)=iconv($charset, $prefs{'charset'}, $from, $to, $subject);
529
}
530
531
$linehtml=$linetemplate;
532
if ($prefs{'uselightbar'}) {
533
$tr_bgcolorstr=qq|bgcolor=$style{tablerow_light} |;
534
$tr_bgcolorstr=qq|bgcolor=$style{tablerow_dark} | if ($totalmessage==1); # make this msg selected if it is the only one
535
$tr_bgcolorstr.=qq|onMouseOver='this.style.backgroundColor=$style{tablerow_hicolor};' |.
536
qq|onMouseOut='this.style.backgroundColor = document.getElementById("$messnum").checked? $style{tablerow_dark}:$style{tablerow_light};' |.
537
qq|onClick='if (!document.layers) {var cb=document.getElementById("$messnum"); cb.checked=!cb.checked}' |.
538
qq|id="tr_$messnum" |;
539
$td_bgcolorstr='';
540
$checkbox_onclickstr='if (!document.layers) {this.checked=!this.checked}'; # disable checkbox change since it is already done once by tr onclick event
541
} else {
542
$tr_bgcolorstr='';
543
$td_bgcolorstr=qq|bgcolor=|.($style{"tablerow_dark"},$style{"tablerow_light"})[$messnum%2];
544
$checkbox_onclickstr='';
545
}
546
# STATUS, choose status icons based on Status: line and type of encoding
547
$temphtml = "<B>$messnum</B> \n";
548
$status =~ s/\s//g; # remove blanks
549
if ( $status =~ /R/i ) {
550
($boldon, $boldoff) = ('', '');
551
my $icon="read.gif"; $icon="read.a.gif" if ($status=~/A/i);
552
$temphtml .= iconlink("$icon", "$lang_text{'markasunread'} ", qq|href="$main_url_with_keyword&amp;action=markasunread&amp;message_id=$escapedmessageid&amp;status=$status&amp;page=$page&amp;longpage=$longpage"|);
553
} else {
554
($boldon, $boldoff) = ('<B>', '</B>');
555
my $icon="unread.gif"; $icon="unread.a.gif" if ($status=~/A/i);
556
$temphtml .= iconlink("$icon", "$lang_text{'markasread'} ", qq|href="$main_url_with_keyword&amp;action=markasread&amp;message_id=$escapedmessageid&amp;status=$status&amp;page=$page&amp;longpage=$longpage"|);
557
}
558
# T flag is only supported by openwebmail internally
559
# see routine update_folderindex in maildb.pl for detail
560
$temphtml .= iconlink("attach.gif", "", "") if ($status =~ /T/i);
561
$temphtml .= iconlink("important.gif", "", "") if ($status =~ /I/i);
562
$temphtml = qq|<td $td_bgcolorstr nowrap>$temphtml&nbsp;</td>\n|;
563
$linehtml =~ s/\@\@\@STATUS\@\@\@/$temphtml/;
564
565
# DATE, convert dateserial(GMT) to localtime
566
$temphtml=ow::datetime::dateserial2str($dateserial,
567
$prefs{'timeoffset'}, $prefs{'daylightsaving'},
568
$prefs{'dateformat'}, $prefs{'hourformat'});
569
$temphtml = qq|<td $td_bgcolorstr>$boldon$temphtml$boldoff</td>\n|;
570
$linehtml =~ s/\@\@\@DATE\@\@\@/$temphtml/;
571
572
# FROM, find name, email of from and to field first
573
my @recvlist = ow::tool::str2list($to,0);
574
my (@namelist, @addrlist);
575
foreach my $recv (@recvlist) {
576
my ($n, $a)=ow::tool::email2nameaddr($recv);
577
# if $n or $a has ", $recv may be an incomplete addr
578
push(@namelist, $n) if ($n!~/"/);
579
push(@addrlist, $a) if ($a!~/"/);;
580
}
581
my ($to_name, $to_address)=(join(",", @namelist), join(",", @addrlist));
582
$to_name=substr($to_name, 0, 29)."..." if (length($to_name)>32);
583
$to_address=substr($to_address, 0, 61)."..." if (length($to_address)>64);
584
my ($from_name, $from_address)=ow::tool::email2nameaddr($from);
585
$from_address=~s/"//g;
586
587
# we aren't interested in the sender of SENT/DRAFT folder,
588
# but the recipient, so display $to instead of $from
589
my ($from2, $from2_name, $from2_address, $from2_searchtype, $from2_keyword);
590
if ( $folder=~ m#sent-mail#i ||
591
$folder=~ m#saved-drafts#i ||
592
$folder=~ m#\Q$lang_folders{'sent-mail'}\E#i ||
593
$folder=~ m#\Q$lang_folders{'saved-drafts'}\E#i ) {
594
($from2, $from2_name, $from2_address)=($to, $to_name, $to_address);
595
($from2_searchtype, $from2_keyword)=('to', join('|',@addrlist));
596
} else {
597
($from2, $from2_name, $from2_address)=($from, $from_name, $from_address);
598
($from2_searchtype, $from2_keyword)=('from', $from_address);
599
}
600
my $from2str=$from2_name;
601
if (!$limited) {
602
$from2str=qq|<a href="$config{'ow_cgiurl'}/openwebmail-send.pl\?action=composemessage&amp;sort=$sort&amp;keyword=$escapedkeyword&amp;searchtype=$searchtype&amp;folder=$escapedfolder&amp;page=$page&amp;sessionid=$thissession&amp;composetype=sendto&amp;to=|.
603
ow::tool::escapeURL($from2).
604
qq|&amp;compose_caller=main" title="$from_address -> $to_address">$from2_name </a>|;
605
}
606
if ($prefs{'useminisearchicon'}) {
607
my $searchstr=iconlink("search.s.gif", "$lang_text{'search'} $from2_address",
608
qq|href="$main_url&amp;action=listmessages&amp;sort=$sort&amp;searchtype=$from2_searchtype&amp;keyword=|.
609
ow::tool::escapeURL($from2_keyword).qq|"| ).
610
qq|&nbsp;|;
611
$temphtml = qq|<td $td_bgcolorstr>|.
612
qq|<table cellspacing="0" cellpadding="0"><tr>\n|.
613
qq|<td>$searchstr</td>|.
614
qq|<td>$boldon$from2str$boldoff</td>\n|.
615
qq|</tr></table></td>\n|;
616
} else {
617
$temphtml=qq|<td $td_bgcolorstr>$boldon$from2str$boldoff</td>\n|;
618
}
619
$linehtml =~ s/\@\@\@FROM\@\@\@/$temphtml/;
620
621
# SUBJECT, cut subject to less than 64
622
$subject=substr($subject, 0, 64)."..." if (length($subject)>67);
623
$subject = ow::htmltext::str2html($subject);
624
$subject = "N/A" if ($subject !~ /[^\s]/); # Make sure there's SOMETHING clickable
625
my $accesskeystr=($messnum-$firstmessage)%10+1; # 1..10
626
if ($accesskeystr == 10) {
627
$accesskeystr=qq|accesskey="0"|;
628
} elsif ($accesskeystr < 10) {
629
$accesskeystr=qq|accesskey="$accesskeystr"|;
630
}
631
632
# param order is purposely same as prev/next links in readmessage,
633
# so the resulted webpage could be cached with same url in both cases
634
$temphtml = qq|<a href="$config{'ow_cgiurl'}/openwebmail-read.pl?|.
635
qq|sessionid=$thissession&amp;folder=$escapedfolder&amp;|.
636
qq|page=$page&amp;longpage=$longpage&amp;|.
637
qq|sort=$sort&amp;keyword=$escapedkeyword&amp;searchtype=$searchtype&amp;|.
638
qq|message_id=$escapedmessageid&amp;action=readmessage&amp;|.
639
qq|headers=$prefs{'headers'}&amp;attmode=simple|;
640
$temphtml.= qq|&amp;db_chkstatus=1| if ($status!~/R/i);
641
$temphtml.= qq|" $accesskeystr title="$lang_text{'charset'}: $charset ">\n|.
642
$subject.
643
qq| </a>\n|;
644
645
my ($subject_begin, $subject_end, $fill) = ('', '', '');
646
for (my $i=1; $i<$messagedepth; $i++) {
647
$fill .= "&nbsp; &nbsp; ";
648
}
649
if ( $messagedepth>0 && $sort eq "subject" ) {
650
$fill .=qq|&nbsp; |.iconlink("follow.up.gif", "", "").qq|&nbsp;|;
651
} elsif ( $messagedepth>0 && $sort eq "subject_rev") {
652
$fill .=qq|&nbsp; |.iconlink("follow.down.gif", "", "").qq|&nbsp;|;
653
}
654
if ($messagedepth) {
655
$subject_begin = qq|<table cellpadding="0" cellspacing="0"><tr><td nowrap>$fill</td><td>|;
656
$subject_end = qq|</td></tr></table>|;
657
}
658
if ($prefs{'useminisearchicon'}) {
659
my $subject2 = $subject; $subject2 =~ s/Res?:\s*//ig; $subject2=~s/\[.*?\]//g;
660
my $searchstr = iconlink("search.s.gif", "$lang_text{'search'} $subject2 ",
661
qq|href="$main_url&amp;action=listmessages&amp;sort=$sort&amp;searchtype=subject&amp;keyword=|.
662
ow::tool::escapeURL($subject2).qq|"| ).
663
qq|&nbsp;|;
664
$temphtml = qq|<td $td_bgcolorstr>|.
665
qq|<table cellspacing="0" cellpadding="0"><tr>\n|.
666
qq|<td>$searchstr</td>|.
667
qq|<td>$subject_begin$boldon$temphtml$boldoff$subject_end</td>\n|.
668
qq|</tr></table></td>\n|;
669
} else {
670
$temphtml = qq|<td $td_bgcolorstr>$subject_begin$boldon$temphtml$boldoff$subject_end</td>\n|;
671
}
672
$linehtml =~ s/\@\@\@SUBJECT\@\@\@/$temphtml/;
673
674
# SIZE, round message size and change to an appropriate unit for display
675
$temphtml = lenstr($messagesize,0);
676
$temphtml = qq|<td align="right" $td_bgcolorstr>$boldon$temphtml$boldoff</td>\n|;
677
$linehtml =~ s/\@\@\@SIZE\@\@\@/$temphtml/;
678
679
# CHECKBOX
680
if ( $totalmessage==1 ) { # make this msg selected if it is the only one
681
$temphtml = checkbox(-name=>'message_ids',
682
-value=>$messageid,
683
-checked=>1,
684
-override=>'1',
685
-label=>'',
686
-onclick=> $checkbox_onclickstr,
687
-id=>$messnum);
688
} else {
689
$temphtml = checkbox(-name=>'message_ids',
690
-value=>$messageid,
691
-override=>'1',
692
-label=>'',
693
-onclick=> $checkbox_onclickstr,
694
-id=>$messnum);
695
}
696
$temphtml = qq|<td align="center" $td_bgcolorstr>$temphtml</td>\n|;
697
$linehtml =~ s/\@\@\@CHECKBOX\@\@\@/$temphtml/;
698
699
$headershtml .= qq|<tr $tr_bgcolorstr>$linehtml</tr>\n\n|;
700
}
701
ow::dbm::close(\%FDB, $folderdb);
702
undef(@{$r_messageids}); undef($r_messageids);
703
704
my $gif;
705
$temphtml=qq|<table cellpadding="0" cellspacing="0" border="0"><tr><td>|;
706
if ($page > 1) {
707
$gif="left.gif"; $gif="right.gif" if ($ow::lang::RTL{$prefs{'language'}});
708
$temphtml .= iconlink($gif, "&lt;", qq|accesskey="U" href="$main_url_with_keyword&amp;action=listmessages&amp;page=|.($page-1).qq|&amp;longpage=$longpage"|);
709
} else {
710
$gif="left-grey.gif"; $gif="right-grey.gif" if ($ow::lang::RTL{$prefs{'language'}});
711
$temphtml .= iconlink($gif, "-", "");
712
}
713
$temphtml.=qq|</td><td>$page/$totalpage</td><td>|;
714
if ($page < $totalpage) {
715
$gif="right.gif"; $gif="left.gif" if ($ow::lang::RTL{$prefs{'language'}});
716
$temphtml .= iconlink($gif, "&gt;", qq|accesskey="D" href="$main_url_with_keyword&amp;action=listmessages&amp;page=|.($page+1) .qq|&amp;longpage=$longpage"|);
717
} else {
718
$gif="right-grey.gif"; $gif="left-grey.gif" if ($ow::lang::RTL{$prefs{'language'}});
719
$temphtml .= iconlink($gif, "-", "");
720
}
721
$temphtml.=qq|</td></tr></table>|;
722
$html =~ s/\@\@\@PAGECONTROL.*\@\@\@/$temphtml/g;
723
724
if ($lastmessage-$firstmessage>10) {
725
$temphtml = iconlink("gotop.gif", "^", qq|href="#"|);
726
$html =~ s/\@\@\@TOPCONTROL\@\@\@/$temphtml/;
727
} else {
728
$html =~ s/\@\@\@TOPCONTROL\@\@\@//;
729
}
730
731
732
my ($htmlsearch, $htmlpage, $htmlmove);
733
734
my %searchtypelabels;
735
foreach (qw(from to subject date attfilename header textcontent all)) {
736
$searchtypelabels{$_}=$lang_text{$_};
737
}
738
$htmlsearch = qq|<table cellspacing="0" cellpadding="0"><tr><td>|.
739
popup_menu(-name=>'searchtype',
740
-default=>'subject',
741
-values=>['from', 'to', 'subject', 'date', 'attfilename', 'header', 'textcontent' ,'all'],
742
-labels=>\%searchtypelabels).
743
qq|</td><td>|.
744
textfield(-name=>'keyword',
745
-default=>$keyword,
746
-size=>'12',
747
-accesskey=>'S', # search folder
748
-override=>'1').
749
qq|</td><td>|.
750
submit(-name =>'searchbutton',
751
-value=>$lang_text{'search'}).
752
qq|</td></tr></table>|;
753
754
my @pagevalues;
755
for (my $p=1; $p<=$totalpage; $p++) {
756
my $pdiff=abs($p-$page);
757
if ($pdiff<10 || $p==1 || $p==$totalpage ||
758
($pdiff<100 && $p%10==0) || ($pdiff<1000 && $p%100==0) || $p%1000==0) {
759
push(@pagevalues, $p);
760
}
761
}
762
$htmlpage=qq|<table cellpadding="0" cellspacing="0"><tr>|.
763
qq|<td>$lang_text{'page'}</td><td>|.
764
popup_menu(-name=>'page',
765
-values=>\@pagevalues,
766
-default=>$page,
767
-onChange=>"JavaScript:document.pageform.submit();",
768
-override=>'1').
769
qq|</td>|.ow::tool::hiddens(longpage=>$longpage).qq|<td>|;
770
if ($longpage) {
771
my $str=$lang_text{'msgsperpage'}; $str=~s/\@\@\@MSGCOUNT\@\@\@/$prefs{'msgsperpage'}/;
772
$htmlpage.=qq|<a href="$main_url_with_keyword&amp;action=listmessages&amp;page=$page&amp;longpage=0" title="$str">&nbsp;-&nbsp;</a>|;
773
} else {
774
my $str=$lang_text{'msgsperpage'}; $str=~s/\@\@\@MSGCOUNT\@\@\@/1000/;
775
$htmlpage.=qq|<a href="$main_url_with_keyword&amp;action=listmessages&amp;page=$page&amp;longpage=1" title="$str">&nbsp;+&nbsp;</a>|;
776
}
777
$htmlpage.=qq|</td></tr></table>|;
778
779
my @movefolders;
780
# option to del message directly from folder
781
if ($quotalimit>0 && $quotausage>=$quotalimit) {
782
@movefolders=('DELETE');
783
} else {
784
foreach (@validfolders) {
785
push (@movefolders, $_) if ($_ ne $folder);
786
}
787
push(@movefolders, 'LEARNSPAM', 'LEARNHAM') if ($config{'enable_learnspam'});
788
push(@movefolders, 'FORWARD', 'DELETE');
789
}
790
my $defaultdestination;
791
if ($quotalimit>0 && $quotausage>=$quotalimit) {
792
$defaultdestination='DELETE';
793
} elsif ($folder eq 'mail-trash' || $folder eq 'spam-mail' || $folder eq 'virus-mail') {
794
$defaultdestination= 'INBOX';
795
} elsif ($folder eq 'sent-mail' || $folder eq 'saved-drafts') {
796
$defaultdestination='mail-trash';
797
} else {
798
$defaultdestination= $prefs{'defaultdestination'} || 'mail-trash';
799
$defaultdestination='mail-trash' if ( $folder eq $defaultdestination);
800
}
801
$htmlmove = qq|<table cellspacing="0" cellpadding="0"><tr><td>|.
802
popup_menu(-name=>'destination',
803
-values=>\@movefolders,
804
-default=>$defaultdestination,
805
-labels=>\%lang_folders,
806
-accesskey=>'T', # target folder
807
-override=>'1').
808
qq|</td><td>|.
809
submit(-name =>'movebutton',
810
-value=>$lang_text{'move'},
811
-onClick=>"return OpConfirm($lang_text{'msgmoveconf'}, $prefs{'confirmmsgmovecopy'})");
812
if (!$limited) {
813
$htmlmove .= qq|</td><td>|.
814
submit(-name =>'copybutton',
815
-value=>$lang_text{'copy'},
816
-onClick=>"return OpConfirm($lang_text{'msgcopyconf'}, $prefs{'confirmmsgmovecopy'})");
817
}
818
$htmlmove .= qq|</td></tr></table>|;
819
820
if ($prefs{'ctrlposition_folderview'} eq 'top') {
821
templateblock_enable($html, 'CONTROLBAR1');
822
templateblock_disable($html, 'CONTROLBAR2');
823
$html =~ s/\@\@\@SEARCH1\@\@\@/$htmlsearch/;
824
$html =~ s/\@\@\@PAGEMENU1\@\@\@/$htmlpage/;
825
$html =~ s/\@\@\@MOVECONTROLS1\@\@\@/$htmlmove/;
826
} else {
827
templateblock_disable($html, 'CONTROLBAR1');
828
templateblock_enable($html, 'CONTROLBAR2');
829
$html =~ s/\@\@\@SEARCH2\@\@\@/$htmlsearch/;
830
$html =~ s/\@\@\@PAGEMENU2\@\@\@/$htmlpage/;
831
$html =~ s/\@\@\@MOVECONTROLS2\@\@\@/$htmlmove/;
832
}
833
834
# show 'you have new messages' at status line
835
if ($folder ne 'INBOX' ) {
836
my $msg;
837
if ($now_inbox_newmessages>0) {
838
$msg="$now_inbox_newmessages $lang_text{'messages'} $lang_text{'unread'}";
839
} elsif ($now_inbox_allmessages>0) {
840
$msg="$now_inbox_allmessages $lang_text{'messages'}";
841
} else {
842
$msg=$lang_text{'nomessages'};
843
}
844
$html.=qq|<script language="JavaScript">\n<!--\n|.
845
qq|window.defaultStatus = "$lang_folders{'INBOX'} : $msg";\n|.
846
qq|//-->\n</script>\n|;
847
}
848
849
# play sound if
850
# a. new msg increases in INBOX
851
if ( $now_inbox_newmessages>$orig_inbox_newmessages ) {
852
if (-f "$config{'ow_htmldir'}/sounds/$prefs{'newmailsound'}" ) {
853
$html.=qq|<embed src="$config{'ow_htmlurl'}/sounds/$prefs{'newmailsound'}" autostart="true" hidden="true">\n|;
854
}
855
}
856
857
$temphtml='';
858
# show quotahit del warning
859
if ($quotahit_deltype ne '') {
860
my $msg=qq|<font size="-1" color="#cc0000">$lang_err{$quotahit_deltype}</font>|;
861
$msg=~s/\@\@\@QUOTALIMIT\@\@\@/$config{'quota_limit'}$lang_sizes{'kb'}/;
862
$msg =~ s!\\!\\\\!g; $msg =~ s!'!\\'!g; # escape ' for javascript
863
$temphtml.=qq|<script language="JavaScript">\n<!--\n|.
864
qq|showmsg('$prefs{"charset"}', '$lang_text{"quotahit"}', '$msg', '$lang_text{"close"}', '_quotahit_del', 400, 100, 60);\n|.
865
qq|//-->\n</script>\n|;
866
}
867
# show quotahit alert
868
if ($quotalimit>0 && $quotausage>=$quotalimit) {
869
my $msg=qq|<font size="-1" color="#cc0000">$lang_err{'quotahit_alert'}</font>|;
870
$msg =~ s!\\!\\\\!g; $msg =~ s!'!\\'!g; # escape ' for javascript
871
$temphtml.=qq|<script language="JavaScript">\n<!--\n|.
872
qq|showmsg('$prefs{"charset"}', '$lang_text{"quotahit"}', '$msg', '$lang_text{"close"}', '_quotahit_alert', 400, 100, 60);\n|.
873
qq|//-->\n</script>\n|;
874
# show spool overlimit alert
875
} elsif ($config{'spool_limit'}>0 && $inboxsize_k>$config{'spool_limit'}) {
876
my $msg=qq|<font size="-1" color="#cc0000">$lang_err{'spool_overlimit'}</font>|;
877
$msg=~s/\@\@\@SPOOLLIMIT\@\@\@/$config{'spool_limit'}$lang_sizes{'kb'}/;
878
$msg =~ s!\\!\\\\!g; $msg =~ s!'!\\'!g; # escape ' for javascript
879
$temphtml.=qq|<script language="JavaScript">\n<!--\n|.
880
qq|showmsg('$prefs{"charset"}', '$lang_text{"quotahit"}', '$msg', '$lang_text{"close"}', '_spool_overlimit', 400, 100, 60);\n|.
881
qq|//-->\n</script>\n|;
882
}
883
# show msgsent confirmation
884
if (defined(param('sentsubject')) && $prefs{'mailsentwindowtime'}>0) {
885
my $msg=qq|<font size="-1">$lang_text{'msgsent'}</font>|;
886
my $sentsubject=param('sentsubject')||'N/A';
887
$msg=~s!\@\@\@SUBJECT\@\@\@!$sentsubject!;
888
$msg =~ s!\\!\\\\!g; $msg =~ s!'!\\'!g; # escape ' for javascript
889
$temphtml.=qq|<script language="JavaScript">\n<!--\n|.
890
qq|showmsg('$prefs{"charset"}', '$lang_text{'send'}', '$msg', '$lang_text{"close"}', '_msgsent', 300, 100, $prefs{'mailsentwindowtime'});\n|.
891
qq|//-->\n</script>\n|;
892
}
893
# popup stat of incoming msgs
894
if ( $prefs{'newmailwindowtime'}>0) {
895
my ($totalfiltered, %filtered)=read_filterfolderdb(1);
896
if ($totalfiltered>0 ||
897
$now_inbox_newmessages>$orig_inbox_newmessages) {
898
my $msg;
899
my $line=0;
900
if ($now_inbox_newmessages>$orig_inbox_newmessages) {
901
$msg .= qq|$lang_folders{'INBOX'} &nbsp; |.($now_inbox_newmessages-$orig_inbox_newmessages).qq|<br>|;
902
$line++;
903
}
904
foreach my $f (get_defaultfolders(), 'DELETE') {
905
if ($filtered{$f}>0) {
906
$msg .= qq|$lang_folders{$f} &nbsp; $filtered{$f}<br>|;
907
$line++;
908
}
909
}
910
foreach my $f (sort keys %filtered) {
911
next if (is_defaultfolder($f));
912
$msg .= qq|$f &nbsp; $filtered{$f}<br>|;
913
$line++;
914
}
915
$msg = qq|<font size="-1">$msg</font>|;
916
$msg =~ s!\\!\\\\!g; $msg =~ s!'!\\'!g; # escape ' for javascript
917
$temphtml.=qq|<script language="JavaScript">\n<!--\n|.
918
qq|showmsg('$prefs{"charset"}', '$lang_text{"inmessages"}', '$msg', '$lang_text{"close"}', '_incoming', 200, |.($line*16+70).qq|, $prefs{'newmailwindowtime'});\n|.
919
qq|//-->\n</script>\n|;
920
}
921
}
922
923
$html.=readtemplate('showmsg.js').$temphtml if ($temphtml);
924
925
# since $headershtml may be large, we put it into $html as late as possible
926
$html =~ s/\@\@\@HEADERS\@\@\@/$headershtml/; undef($headershtml);
927
928
# since some browsers always treat refresh directive as realtive url.
929
# we use relative path for refresh
930
my $refreshinterval=$prefs{'refreshinterval'}*60;
931
my $relative_url="$config{'ow_cgiurl'}/openwebmail-main.pl";
932
$relative_url=~s!/.*/!!g;
933
934
httpprint([-Refresh=>"$refreshinterval;URL=$relative_url?sessionid=$thissession&sort=$sort&keyword=$escapedkeyword&searchtype=$searchtype&folder=INBOX&action=listmessages&page=1&session_noupdate=1"],
935
[htmlheader(), htmlplugin($config{'header_pluginfile'}),
936
$html,
937
htmlplugin($config{'footer_pluginfile'}), htmlfooter(2)] );
938
}
939
940
# reminder for events within 7 days
941
sub eventreminder_html {
942
my ($reminderdays)=@_;
943
944
my $localtime=ow::datetime::time_gm2local(time(), $prefs{'timeoffset'}, $prefs{'daylightsaving'});
945
my ($year, $month, $day, $hour, $min)=(ow::datetime::seconds2array($localtime))[5,4,3,2,1];
946
$year+=1900; $month++;
947
my $hourmin=sprintf("%02d%02d", $hour, $min);
948
949
my $calbookfile=dotpath('calendar.book');
950
my (%items, %indexes);
951
if ( readcalbook($calbookfile, \%items, \%indexes, 0)<0 ) {
952
openwebmailerror(__FILE__, __LINE__, "$lang_err{'couldnt_open'} $calbookfile");
953
}
954
if ($prefs{'calendar_reminderforglobal'}) {
955
readcalbook("$config{'global_calendarbook'}", \%items, \%indexes, 1E6);
956
if ($prefs{'calendar_holidaydef'} eq 'auto') {
957
readcalbook("$config{'ow_holidaysdir'}/$prefs{'language'}", \%items, \%indexes, 1E7);
958
} elsif ($prefs{'calendar_holidaydef'} ne 'none') {
959
readcalbook("$config{'ow_holidaysdir'}/$prefs{'calendar_holidaydef'}", \%items, \%indexes, 1E7);
960
}
961
}
962
963
my $event_count=0;
964
my %used; # tag used index so an item won't be show more than once in case it is a regexp
965
my $temphtml="";
966
for my $x (0..$reminderdays-1) {
967
my $wdaynum;
968
($wdaynum, $year, $month, $day)=(ow::datetime::seconds2array($localtime+$x*86400))[6,5,4,3];
969
$year+=1900; $month++;
970
my $dow=$ow::datetime::wday_en[$wdaynum];
971
my $date=sprintf("%04d%02d%02d", $year,$month,$day);
972
my $date2=sprintf("%04d,%02d,%02d,%s", $year,$month,$day,$dow);
973
974
my @indexlist=();
975
push(@indexlist, @{$indexes{$date}}) if (defined($indexes{$date}));
976
push(@indexlist, @{$indexes{'*'}}) if (defined($indexes{'*'}));
977
@indexlist=sort { ($items{$a}{'starthourmin'}||1E9)<=>($items{$b}{'starthourmin'}||1E9) } @indexlist;
978
979
my $dayhtml="";
980
for my $index (@indexlist) {
981
next if ($used{$index});
982
if ($date=~/$items{$index}{'idate'}/ ||
983
$date2=~/$items{$index}{'idate'}/ ||
984
ow::datetime::easter_match($year,$month,$day,$items{$index}{'idate'}) ) {
985
if ($items{$index}{'starthourmin'}>=$hourmin ||
986
$items{$index}{'starthourmin'}==0 ||
987
$x>0) {
988
$event_count++;
989
$used{$index}=1;
990
last if ($event_count>5);
991
my ($t, $s);
992
993
if ($items{$index}{'starthourmin'}=~/(\d+)(\d\d)/) {
994
if ($prefs{'hourformat'}==12) {
995
my ($h, $ampm)=ow::datetime::hour24to12($1);
996
$t="$h:$2$ampm";
997
} else {
998
$t="$1:$2";
999
}
1000
if ($items{$index}{'endhourmin'}=~/(\d+)(\d\d)/) {
1001
if ($prefs{'hourformat'}==12) {
1002
my ($h, $ampm)=ow::datetime::hour24to12($1);
1003
$t.="-$h:$2$ampm";
1004
} else {
1005
$t.="-$1:$2";
1006
}
1007
}
1008
} else {
1009
$t='#';
1010
}
1011
$s=$items{$index}{'string'};
1012
$s=substr($s,0,20).".." if (length($s)>=21);
1013
$s.='*' if ($index>=1E6);
1014
$dayhtml.=qq|&nbsp; | if $dayhtml ne "";
1015
$dayhtml.=qq|<font class="smallcolortext">$t </font><font class="smallblacktext">$s</font>|;
1016
}
1017
}
1018
}
1019
if ($dayhtml ne "") {
1020
my $title=$prefs{'dateformat'}||"mm/dd/yyyy";
1021
my ($m, $d)=(sprintf("%02d",$month), sprintf("%02d",$day));
1022
$title=~s/yyyy/$year/; $title=~s/mm/$m/; $title=~s/dd/$d/;
1023
if ($lang_text{'calfmt_yearmonthdaywday'} =~ /^\s*\@\@\@WEEKDAY\@\@\@/) {
1024
$title="$lang_wday{$wdaynum} $title";
1025
} else {
1026
$title="$title $lang_wday{$wdaynum}";
1027
}
1028
$temphtml.=qq| &nbsp; | if ($temphtml ne"");
1029
$temphtml.=qq|<font class="smallblacktext">[+$x] </font>| if ($x>0);
1030
$temphtml.=qq|<a href="$config{'ow_cgiurl'}/openwebmail-cal.pl?sessionid=$thissession&amp;folder=$escapedfolder&amp;|.
1031
qq|action=calday&amp;year=$year&amp;month=$month&amp;day=$day" title="$title">$dayhtml</a>\n|;
1032
}
1033
}
1034
$temphtml .= " &nbsp; ..." if ($event_count>5);
1035
1036
$temphtml=qq|&nbsp;$temphtml|;
1037
return($temphtml);
1038
}
1039
########## END LISTMESSAGES ######################################
1040
1041
########## MARKASREAD ############################################
1042
sub markasread {
1043
my $messageid = param('message_id');
1044
return if ($messageid eq "");
1045
1046
my ($folderfile, $folderdb)=get_folderpath_folderdb($user, $folder);
1047
my @attr=get_message_attributes($messageid, $folderdb);
1048
return if ($#attr<0); # msg not found in db
1049
1050
if ($attr[$_STATUS] !~ /R/i) {
1051
ow::filelock::lock($folderfile, LOCK_EX) or
1052
openwebmailerror(__FILE__, __LINE__, "$lang_err{'couldnt_lock'} $folderfile!");
1053
update_message_status($messageid, $attr[$_STATUS]."R", $folderdb, $folderfile);
1054
ow::filelock::lock($folderfile, LOCK_UN);
1055
}
1056
}
1057
########## END MARKASREAD ########################################
1058
1059
########## MARKASUNREAD ##########################################
1060
sub markasunread {
1061
my $messageid = param('message_id');
1062
return if ($messageid eq "");
1063
1064
my ($folderfile, $folderdb)=get_folderpath_folderdb($user, $folder);
1065
my @attr=get_message_attributes($messageid, $folderdb);
1066
return if ($#attr<0); # msg not found in db
1067
1068
if ($attr[$_STATUS] =~ /[RV]/i) {
1069
# clear flag R(read), V(verified by mailfilter)
1070
my $newstatus=$attr[$_STATUS];
1071
$newstatus=~s/[RV]//ig;
1072
1073
ow::filelock::lock($folderfile, LOCK_EX) or
1074
openwebmailerror(__FILE__, __LINE__, "$lang_err{'couldnt_lock'} $folderfile!");
1075
update_message_status($messageid, $newstatus, $folderdb, $folderfile);
1076
ow::filelock::lock($folderfile, LOCK_UN);
1077
}
1078
}
1079
########## END MARKASUNREAD ######################################
1080
1081
########## MOVEMESSAGE ###########################################
1082
sub movemessage {
1083
my ($r_messageids, $destination)=@_;
1084
if ($destination eq $folder) {
1085
openwebmailerror(__FILE__, __LINE__, "$lang_err{'shouldnt_move_here'}");
1086
}
1087
1088
my $op='move';
1089
if ($destination eq 'DELETE') { # copy to DELETE is meaningless, so return
1090
return if (defined(param('copybutton'))); # copy to delete =>nothing to do
1091
$op='delete';
1092
} else {
1093
$op='copy' if (defined(param('copybutton'))); # copy button pressed
1094
}
1095
if ($quotalimit>0 && $quotausage>$quotalimit && $op ne "delete") {
1096
openwebmailerror(__FILE__, __LINE__, "$lang_err{'quotahit_alert'}");
1097
}
1098
1099
my ($learntype, $learnfolder)=('none', $folder);
1100
if ($destination eq 'LEARNSPAM') {
1101
$learntype='learnspam';
1102
$destination=$folder; # default no move by set dst=src
1103
if ($folder ne 'spam-mail' && $folder ne 'virus-mail') {
1104
$learnfolder=$destination=$config{'learnspam_destination'}; # we will move spam if it was not in spam/virus
1105
}
1106
} elsif ($destination eq 'LEARNHAM') {
1107
$learntype='learnham';
1108
$destination=$folder; # default no move by set dst=src
1109
if ($folder eq 'mail-trash' || $folder eq 'spam-mail' || $folder eq 'virus-mail') {
1110
$learnfolder=$destination=$config{'learnham_destination'}; # we will move ham if it was in trash/spam/virus
1111
}
1112
}
1113
1114
my ($folderfile, $folderdb)=get_folderpath_folderdb($user, $folder);
1115
my ($dstfile, $dstdb)=get_folderpath_folderdb($user, $destination);
1116
my $counted=0;
1117
1118
if (!-f $folderfile) {
1119
openwebmailerror(__FILE__, __LINE__, "$folderfile $lang_err{'doesnt_exist'}");
1120
}
1121
if ($folder ne $destination) {
1122
ow::filelock::lock($folderfile, LOCK_EX) or
1123
openwebmailerror(__FILE__, __LINE__, "$lang_err{'couldnt_lock'} $folderfile!");
1124
1125
if ($destination eq 'DELETE') {
1126
$counted=operate_message_with_ids($op, $r_messageids, $folderfile, $folderdb);
1127
} else {
1128
if (!-f "$dstfile" ) {
1129
if (!open (F,">>$dstfile")) {
1130
my $err=$!;
1131
ow::filelock::lock($folderfile, LOCK_UN);
1132
openwebmailerror(__FILE__, __LINE__, "$lang_err{'couldnt_open'} $lang_err{'destination_folder'} $dstfile! ($err)");
1133
}
1134
close(F);
1135
}
1136
if (!ow::filelock::lock($dstfile, LOCK_EX)) {
1137
ow::filelock::lock($folderfile, LOCK_UN);
1138
openwebmailerror(__FILE__, __LINE__, "$lang_err{'couldnt_lock'} $dstfile!");
1139
}
1140
$counted=operate_message_with_ids($op, $r_messageids, $folderfile, $folderdb, $dstfile, $dstdb);
1141
}
1142
folder_zapmessages($folderfile, $folderdb) if ($counted>0);
1143
1144
ow::filelock::lock($dstfile, LOCK_UN);
1145
ow::filelock::lock($folderfile, LOCK_UN);
1146
}
1147
1148
# fork a child to do learn the msg in background
1149
# thus the resulted msglist can be returned as soon as possible
1150
if ($learntype ne 'none') {
1151
local $SIG{CHLD} = 'IGNORE'; # handle zombie
1152
local $|=1; # flush all output
1153
if ( fork() == 0 ) { # child
1154
close(STDIN); close(STDOUT); close(STDERR);
1155
ow::suid::drop_ruid_rgid(); # set ruid=euid to avoid fork in spamcheck.pl
1156
1157
my ($totallearned, $totalexamed)=(0,0);
1158
my ($learnfile, $learndb)=get_folderpath_folderdb($user, $learnfolder);
1159
my $learnhandle=FileHandle->new();
1160
foreach my $messageid (@{$r_messageids}) {
1161
my ($msgsize, $errmsg, $block, $learned, $examed);
1162
($msgsize, $errmsg)=lockget_message_block($messageid, $learnfile, $learndb, \$block);
1163
next if ($msgsize<=0);
1164
1165
if ($learntype eq 'learnspam') {
1166
($learned, $examed)=ow::spamcheck::learnspam($config{'learnspam_pipe'}, \$block);
1167
} else {
1168
($learned, $examed)=ow::spamcheck::learnham($config{'learnham_pipe'}, \$block);
1169
}
1170
if ($learned==-99999) {
1171
my $m="$learntype - error ($examed) at $messageid";
1172
writelog($m); writehistory($m);
1173
last;
1174
} else {
1175
$totallearned+=$learned;
1176
$totalexamed+=$examed;
1177
}
1178
}
1179
my $m="$learntype - $totallearned learned, $totalexamed examined";
1180
writelog($m); writehistory($m);
1181
1182
openwebmail_exit(0);
1183
}
1184
}
1185
1186
if ($counted>0){
1187
my $msg;
1188
if ( $op eq 'move') {
1189
$msg="move message - move $counted msgs from $folder to $destination - ids=".join(", ", @{$r_messageids});
1190
} elsif ($op eq 'copy' ) {
1191
$msg="copy message - copy $counted msgs from $folder to $destination - ids=".join(", ", @{$r_messageids});
1192
} else {
1193
$msg="delete message - delete $counted msgs from $folder - ids=".join(", ", @{$r_messageids});
1194
# recalc used quota for del if user quotahit
1195
if ($quotalimit>0 && $quotausage>$quotalimit) {
1196
$quotausage=(ow::quota::get_usage_limit(\%config, $user, $homedir, 1))[2];
1197
}
1198
}
1199
writelog($msg);
1200
writehistory($msg);
1201
} elsif ($counted==-1) {
1202
openwebmailerror(__FILE__, __LINE__, "$lang_err{'inv_msg_op'}");
1203
} elsif ($counted==-2) {
1204
openwebmailerror(__FILE__, __LINE__, "$lang_err{'couldnt_open'} $folderfile");
1205
} elsif ($counted==-3) {
1206
openwebmailerror(__FILE__, __LINE__, "$lang_err{'couldnt_open'} $dstfile!");
1207
}
1208
return;
1209
}
1210
########## END MOVEMESSAGE #######################################
1211
1212
########## EMPTYFOLDER ############################################
1213
sub www_emptyfolder {
1214
my $folder=$_[0];
1215
my ($folderfile, $folderdb)=get_folderpath_folderdb($user, $folder);
1216
1217
ow::filelock::lock($folderfile, LOCK_EX) or
1218
openwebmailerror(__FILE__, __LINE__, "$lang_err{'couldnt_lock'} $folderfile!");
1219
my $ret=empty_folder($folderfile, $folderdb);
1220
ow::filelock::lock($folderfile, LOCK_UN);
1221
1222
if ($ret==-1) {
1223
openwebmailerror(__FILE__, __LINE__, "$lang_err{'couldnt_open'} $folderfile!");
1224
} elsif ($ret==-2) {
1225
openwebmailerror(__FILE__, __LINE__, "$lang_err{'couldnt_updatedb'} db $folderdb");
1226
}
1227
writelog("emptyfolder - $folder");
1228
writehistory("emptyfolder - $folder");
1229
}
1230
########## END EMPTYFOLDER ########################################
1231
1232
########## RETRIVEPOP3/RETRPOP3S #################################
1233
sub www_pop3_fetch {
1234
my $pop3host = param('pop3host') || '';
1235
my $pop3port = param('pop3port') || '110';
1236
my $pop3user = param('pop3user') || '';
1237
my $pop3book = dotpath('pop3.book');
1238
return if ($pop3host eq '' || $pop3user eq '' || !-f $pop3book);
1239
1240
foreach ( @{$config{'pop3_disallowed_servers'}} ) {
1241
openwebmailerror(__FILE__, __LINE__, "$lang_err{'disallowed_pop3'} $pop3host") if ($pop3host eq $_);
1242
}
1243
my %accounts;
1244
if (readpop3book($pop3book, \%accounts) <0) {
1245
openwebmailerror(__FILE__, __LINE__, "$lang_err{'couldnt_open'} $pop3book!");
1246
}
1247
# don't care enable flag since this is triggered by user clicking
1248
my ($pop3ssl, $pop3passwd, $pop3del)
1249
=(split(/\@\@\@/, $accounts{"$pop3host:$pop3port\@\@\@$pop3user"}))[2,4,5];
1250
1251
my ($ret, $errmsg)=pop3_fetch($pop3host,$pop3port,$pop3ssl, $pop3user,$pop3passwd,$pop3del);
1252
if ($ret<0) {
1253
openwebmailerror(__FILE__, __LINE__, "$errmsg at $pop3user\@$pop3host:$pop3port");
1254
}
1255
}
1256
1257
sub pop3_fetch {
1258
my ($pop3host, $pop3port, $pop3ssl, $pop3user, $pop3passwd, $pop3del)=@_;
1259
1260
my ($ret, $errmsg)=fetchmail($pop3host, $pop3port, $pop3ssl,
1261
$pop3user, $pop3passwd, $pop3del);
1262
if ($ret<0) {
1263
writelog("pop3 error - $errmsg at $pop3user\@$pop3host:$pop3port");
1264
writehistory("pop3 error - $errmsg at $pop3user\@$pop3host:pop3port");
1265
}
1266
return($ret, $errmsg);
1267
}
1268
1269
sub authpop3_fetch {
1270
return 0 if (!$config{'authpop3_getmail'});
1271
1272
my $authpop3book=dotpath('authpop3.book');
1273
my %accounts;
1274
if ( -f "$authpop3book") {
1275
if (readpop3book($authpop3book, \%accounts)>0) {
1276
my $login=$user; $login.="\@$domain" if ($config{'auth_withdomain'});
1277
my ($pop3ssl, $pop3passwd, $pop3del)
1278
=(split(/\@\@\@/, $accounts{"$config{'authpop3_server'}:$config{'authpop3_port'}\@\@\@$login"}))[2,4,5];
1279
# don't case enable flag since noreason to stop fetch from auth server
1280
return pop3_fetch($config{'authpop3_server'},$config{'authpop3_port'},$pop3ssl, $login,$pop3passwd,$pop3del);
1281
} else {
1282
writelog("pop3 error - couldn't open $authpop3book");
1283
writehistory("pop3 error - couldn't open $authpop3book");
1284
}
1285
}
1286
return 0;
1287
}
1288
1289
sub www_pop3_fetches {
1290
return if (! -f dotpath('pop3.book'));
1291
if (update_pop3check()) {
1292
authpop3_fetch() if ($config{'auth_module'} eq 'auth_pop3.pl' ||
1293
$config{'auth_module'} eq 'auth_ldap_vpopmail.pl');
1294
}
1295
pop3_fetches(10); # wait background fetching for no more 10 second
1296
}
1297
1298
use vars qw($pop3_fetches_complete);
1299
sub pop3_fetches {
1300
my $timeout=$_[0];
1301
my $pop3book=dotpath('pop3.book');
1302
my %accounts;
1303
1304
return 0 if ( ! -f "$pop3book" );
1305
if (readpop3book("$pop3book", \%accounts)<0) {
1306
openwebmailerror(__FILE__, __LINE__, "$lang_err{'couldnt_open'} $pop3book!");
1307
}
1308
1309
# fork a child to do fetch pop3 mails and return immediately
1310
if (%accounts>0) {
1311
local $|=1; # flush all output
1312
local $pop3_fetches_complete=0; # localize for reentry safe
1313
local $SIG{CHLD} = sub { wait; $pop3_fetches_complete=1; }; # handle zombie
1314
1315
if ( fork() == 0 ) { # child
1316
close(STDIN); close(STDOUT); close(STDERR);
1317
ow::suid::drop_ruid_rgid(); # set ruid=euid can avoid fork in spamcheck.pl
1318
1319
foreach (values %accounts) {
1320
my ($pop3host,$pop3port,$pop3ssl, $pop3user,$pop3passwd, $pop3del, $enable)=split(/\@\@\@/,$_);
1321
next if (!$enable);
1322
1323
my $disallowed=0;
1324
foreach ( @{$config{'pop3_disallowed_servers'}} ) {
1325
if ($pop3host eq $_) {
1326
$disallowed=1; last;
1327
}
1328
}
1329
next if ($disallowed);
1330
my ($ret, $errmsg) = fetchmail($pop3host, $pop3port, $pop3ssl,
1331
$pop3user, $pop3passwd, $pop3del);
1332
if ($ret<0) {
1333
writelog("pop3 error - $errmsg at $pop3user\@$pop3host:$pop3port");
1334
writehistory("pop3 error - $errmsg at $pop3user\@$pop3host:$pop3port");
1335
}
1336
}
1337
openwebmail_exit(0);
1338
}
1339
1340
for (my $i=0; $i<$timeout; $i++) { # wait fetch to complete for $timeout seconds
1341
sleep 1;
1342
last if ($pop3_fetches_complete);
1343
}
1344
}
1345
1346
return 0;
1347
}
1348
1349
sub update_pop3check {
1350
my $now=time();
1351
my $pop3checkfile=dotpath('pop3.check');
1352
1353
my $ftime=(stat($pop3checkfile))[9];
1354
1355
if (!$ftime) { # create if not exist
1356
open (F, "> $pop3checkfile") or
1357
openwebmailerror(__FILE__, __LINE__, "$lang_err{'couldnt_open'} $pop3checkfile! ($!)");
1358
print F "pop3check timestamp file";
1359
close (F);
1360
}
1361
if ( $now-$ftime > $config{'fetchpop3interval'}*60 ) {
1362
utime($now-1, $now-1, ow::tool::untaint($pop3checkfile)); # -1 is trick for nfs
1363
return 1;
1364
} else {
1365
return 0;
1366
}
1367
}
1368
########## END RETRIVEPOP3/RETRPOP3S #############################
1369
1370
########## MOVEOLDMSG2SAVED ######################################
1371
sub moveoldmsg2saved {
1372
my ($srcfile, $srcdb)=get_folderpath_folderdb($user, 'INBOX');
1373
my ($dstfile, $dstdb)=get_folderpath_folderdb($user, 'saved-messages');
1374
my $counted;
1375
1376
ow::filelock::lock($srcfile, LOCK_EX) or
1377
openwebmailerror(__FILE__, __LINE__, "$lang_err{'couldnt_lock'} $srcfile!");
1378
ow::filelock::lock($dstfile, LOCK_EX) or
1379
openwebmailerror(__FILE__, __LINE__, "$lang_err{'couldnt_lock'} $dstfile!");
1380
1381
$counted=move_oldmsg_from_folder($srcfile, $srcdb, $dstfile, $dstdb);
1382
1383
ow::filelock::lock($dstfile, LOCK_UN);
1384
ow::filelock::lock($srcfile, LOCK_UN);
1385
1386
if ($counted>0){
1387
my $msg="move message - move $counted old msgs from INBOX to saved-messages";
1388
writelog($msg);
1389
writehistory($msg);
1390
} elsif ($counted==-1) {
1391
openwebmailerror(__FILE__, __LINE__, "$lang_err{'inv_msg_op'}");
1392
} elsif ($counted==-2) {
1393
openwebmailerror(__FILE__, __LINE__, "$lang_err{'couldnt_open'} $srcfile");
1394
} elsif ($counted==-3) {
1395
openwebmailerror(__FILE__, __LINE__, "$lang_err{'couldnt_open'} $dstfile!");
1396
}
1397
}
1398
########## END MOVEOLDMSG2SAVED ##################################
1399
1400
########## CLEANTRASH ############################################
1401
sub clean_trash_spamvirus {
1402
my $now=time();
1403
my $trashcheckfile=dotpath('trash.check');
1404
my $ftime=(stat($trashcheckfile))[9];
1405
if (!$ftime) { # create if not exist
1406
open (TRASHCHECK, ">$trashcheckfile" ) or
1407
openwebmailerror(__FILE__, __LINE__, "$lang_err{'couldnt_open'} $trashcheckfile! ($!)");
1408
print TRASHCHECK "trashcheck timestamp file";
1409
close (TRASHCHECK);
1410
}
1411
1412
my %reserveddays=('mail-trash' => $prefs{'trashreserveddays'},
1413
'spam-mail' => $prefs{'spamvirusreserveddays'},
1414
'virus-mail' => $prefs{'spamvirusreserveddays'} );
1415
my (@f, $msg);
1416
push(@f, 'virus-mail') if ($config{'has_virusfolder_by_default'});
1417
push(@f, 'spam-mail') if ($config{'has_spamfolder_by_default'});
1418
push(@f, 'mail-trash');
1419
foreach my $folder (@f) {
1420
next if ($reserveddays{$folder}<0 || $reserveddays{$folder}>=999999);
1421
1422
my ($folderfile, $folderdb)=get_folderpath_folderdb($user, $folder);
1423
1424
ow::filelock::lock($folderfile, LOCK_EX) or
1425
openwebmailerror(__FILE__, __LINE__, "$lang_err{'couldnt_lock'} $folderfile!");
1426
if ($reserveddays{$folder}==0) { # empty folder
1427
my $ret=empty_folder($folderfile, $folderdb);
1428
if ($ret == 0) {
1429
$msg.=', ' if ($msg ne '');
1430
$msg.="all msg deleted from $folder";
1431
}
1432
} elsif ( $now-$ftime > 43200 ) { # do clean only if last clean has passed for more than 0.5 day (43200 sec)
1433
my $deleted=delete_message_by_age($reserveddays{$folder}, $folderdb, $folderfile);
1434
if ($deleted > 0) {
1435
$msg.=', ' if ($msg ne '');
1436
$msg.="$deleted msg deleted from $folder";
1437
}
1438
}
1439
ow::filelock::lock($folderfile, LOCK_UN);
1440
}
1441
if ($msg ne '') {
1442
writelog("clean trash - $msg");
1443
writehistory("clean trash - $msg");
1444
}
1445
1446
if ( $now-$ftime > 43200 ) { # mor than half day, update timestamp of checkfile
1447
utime($now-1, $now-1, ow::tool::untaint($trashcheckfile)); # -1 is trick for nfs
1448
}
1449
return;
1450
}
1451
########## END CLEANTRASH ########################################
1452
1453
########## LOGOUT ################################################
1454
sub logout {
1455
unlink "$config{'ow_sessionsdir'}/$thissession";
1456
autologin_rm(); # disable next autologin for specific ip/browser/user
1457
writelog("logout - $thissession");
1458
writehistory("logout - $thissession");
1459
1460
my ($html, $temphtml);
1461
$html = applystyle(readtemplate("logout.template"));
1462
1463
my $start_url=$config{'start_url'};
1464
1465
if (cookie("openwebmail-ssl")) { # backto SSL
1466
$start_url="https://$ENV{'HTTP_HOST'}$start_url" if ($start_url!~s!^https?://!https://!i);
1467
}
1468
$temphtml = startform(-action=>"$start_url");
1469
$temphtml .= ow::tool::hiddens(logindomain=>$default_logindomain) if ($default_logindomain);
1470
$temphtml .= submit("$lang_text{'loginagain'}").
1471
"&nbsp; &nbsp;".
1472
button(-name=>'exit',
1473
-value=>$lang_text{'exit'},
1474
-onclick=>'javascript:top.window.close();',
1475
-override=>'1').
1476
end_form();
1477
$html =~ s/\@\@\@BUTTONS\@\@\@/$temphtml/;
1478
1479
# clear session cookie at logout
1480
my $cookie= cookie(-name => "$user-sessionid",
1481
-value => '',
1482
-path => '/',
1483
-expires => '+1s');
1484
httpprint([-cookie => $cookie], [htmlheader(), $html, htmlfooter(2)]);
1485
}
1486
########## END LOGOUT ############################################
1487