1<?php
2
3/**
4  * SquirrelMail Spam Buttons Plugin
5  * Copyright (c) 2005-2009 Paul Lesniewski <paul@squirrelmail.org>,
6  * Licensed under the GNU GPL. For full terms see the file COPYING.
7  *
8  * @package plugins
9  * @subpackage spam_buttons
10  *
11  */
12
13
14
15/**
16  * Takes care of spam/ham button click
17  *
18  */
19function sb_button_action_do($args)
20{
21
22   include_once(SM_PATH . 'plugins/spam_buttons/functions.php');
23
24   global $is_spam_shell_command, $is_spam_resend_destination,
25          $is_not_spam_shell_command, $is_not_spam_resend_destination,
26          $is_spam_subject_prefix, $is_not_spam_subject_prefix,
27          $sb_reselect_messages, $sb_delete_after_report,
28          $sb_reselect_messages_allow_override, $username, $data_dir,
29          $sb_delete_after_report_allow_override,
30          $sb_move_after_report_spam, $sb_move_after_report_spam_allow_override,
31          $sb_move_after_report_not_spam, $note,
32          $sb_move_after_report_not_spam_allow_override,
33          $sb_report_spam_by_move_to_folder,
34          $sb_report_not_spam_by_move_to_folder,
35          $sb_copy_after_report_spam_allow_override, $sb_copy_after_report_spam,
36          $sb_copy_after_report_not_spam_allow_override,
37          $sb_copy_after_report_not_spam, $sb_report_spam_by_copy_to_folder,
38          $sb_report_not_spam_by_copy_to_folder,
39          $reported_spam_text, $reported_not_spam_text,
40          $sb_move_to_other_message_after_report, $location,
41          $sb_move_to_other_message_after_report_allow_override,
42          $abort_message_view, $extra_buttons, $is_spam_keep_copy_in_sent,
43          $sb_report_spam_by_custom_function, $is_not_spam_keep_copy_in_sent,
44          $sb_report_not_spam_by_custom_function;
45
46   spam_buttons_init();
47
48
49   if ($sb_reselect_messages_allow_override)
50   {
51      $sb_reselect_messages = getPref($data_dir, $username,
52                                      'sb_reselect_messages', $sb_reselect_messages);
53   }
54   if ($sb_delete_after_report_allow_override)
55   {
56      $sb_delete_after_report = getPref($data_dir, $username,
57                                        'sb_delete_after_report', $sb_delete_after_report);
58   }
59   if ($sb_move_after_report_spam_allow_override)
60   {
61      $sb_move_after_report_spam = getPref($data_dir, $username,
62                                           'sb_move_after_report_spam',
63                                           $sb_move_after_report_spam);
64
65   }
66   if ($sb_move_after_report_not_spam_allow_override)
67   {
68      $sb_move_after_report_not_spam = getPref($data_dir, $username,
69                                               'sb_move_after_report_not_spam',
70                                               $sb_move_after_report_not_spam);
71   }
72   if ($sb_copy_after_report_spam_allow_override)
73   {
74      $sb_copy_after_report_spam = getPref($data_dir, $username,
75                                           'sb_copy_after_report_spam',
76                                           $sb_copy_after_report_spam);
77   }
78   if ($sb_copy_after_report_not_spam_allow_override)
79   {
80      $sb_copy_after_report_not_spam = getPref($data_dir, $username,
81                                               'sb_copy_after_report_not_spam',
82                                               $sb_copy_after_report_not_spam);
83   }
84   if ($sb_move_to_other_message_after_report_allow_override)
85   {
86      $sb_move_to_other_message_after_report = getPref($data_dir, $username,
87                                               'sb_move_to_other_message_after_report',
88                                               $sb_move_to_other_message_after_report);
89   }
90
91
92//sm_print_r($_GET, $_POST, $_SERVER);
93//sm_print_r($_SESSION);
94//exit;
95
96
97   $passed_ent_id = 0;
98   sqGetGlobalVar('passed_ent_id',   $passed_ent_id,  SQ_FORM);
99   sqGetGlobalVar('REQUEST_METHOD',  $method,         SQ_SERVER);
100
101   if (sqGetGlobalVar('location', $location, SQ_POST))
102      { /* $location = htmlspecialchars($location); */ }
103   else
104      $location = php_self();
105
106   if (sqGetGlobalVar('passed_id', $passed_id, SQ_FORM))
107      // fix for Dovecot UIDs can be bigger than normal integers
108      $passed_id = (preg_match('/^[0-9]+$/', $passed_id) ? $passed_id : '0');
109
110   if (sqGetGlobalVar('msg', $msg, SQ_FORM))
111      // fix for Dovecot UIDs can be bigger than normal integers
112      if (is_array($msg)) foreach ($msg as $i => $messageID)
113         $msg[$i] = (preg_match('/^[0-9]+$/', $messageID) ? $messageID : '0');
114      else
115         $msg = (preg_match('/^[0-9]+$/', $msg) ? $msg : '0');
116
117
118   // determine if the report was done from the message view screen
119   //
120   // the use of get_current_hook_name() means the Compatibility plugin is required
121   //
122   $hook_name = get_current_hook_name($args);
123   $move_to_message_after_report = -1;
124   if ($hook_name == 'read_body_header' || $hook_name == 'template_construct_read_headers.tpl')
125   {
126      $reporting_from_message_view = TRUE;
127
128      // get previous/next message UIDs before we possibly move/delete the current one
129      //
130      if (strtolower($sb_move_to_other_message_after_report) == 'next')
131         $move_to_message_after_report = spam_buttons_findNextMessage($passed_id);
132      else if (strtolower($sb_move_to_other_message_after_report) == 'previous')
133         $move_to_message_after_report = spam_buttons_findPreviousMessage($passed_id);
134   }
135   else
136   {
137      $reporting_from_message_view = FALSE;
138   }
139
140
141   // if in 1.4.x we need to print message
142   // to user after report, do that here
143   //
144   if (!check_sm_version(1, 5, 0) && sqGetGlobalVar('sb_note', $sb_note, SQ_SESSION))
145   {
146      echo html_tag('div', '<b>' . $sb_note .'</b>', 'center') . "<br />\n";
147      sqsession_unregister('sb_note');
148   }
149
150
151   // pull button/link flags differently since during
152   // POST submissions, the $_GET array sticks around
153   //
154   $isSpam = NULL;
155   $notSpam = NULL;
156   $extraButton = NULL;
157   $callback = NULL;
158   $custom_button_success_singular = '';
159   $custom_button_success_plural = '';
160   $button_name = NULL;
161   if (strtoupper($method) == 'POST')
162   {
163      sqGetGlobalVar('isSpam',  $isSpam,  SQ_POST);
164      sqGetGlobalVar('notSpam', $notSpam, SQ_POST);
165   }
166   else
167   {
168      sqGetGlobalVar('isSpam',  $isSpam,  SQ_GET);
169      sqGetGlobalVar('notSpam', $notSpam, SQ_GET);
170   }
171
172
173   // detect if extra button was clicked
174   //
175   if (is_null($isSpam) && is_null($notSpam) && !empty($extra_buttons))
176   {
177      foreach ($extra_buttons as $button => $button_info)
178      {
179         $button_name = preg_replace('/[^a-zA-Z0-9]/', '_', $button);
180         if ((strtoupper($method) == 'POST'
181           && sqGetGlobalVar($button_name, $extraButton, SQ_POST))
182          || (strtoupper($method) == 'GET'
183           && sqGetGlobalVar($button_name, $extraButton, SQ_GET)))
184         {
185            if (!empty($button_info[3]))
186               $callback = $button_info[3];
187            if (!empty($button_info[4]))
188               $custom_button_success_singular = $button_info[4];
189            if (!empty($button_info[5]))
190               $custom_button_success_plural = $button_info[5];
191            break;
192         }
193      }
194   }
195
196
197   // build message ID array if user came from one of the
198   // links on the message view page
199   //
200   if ($isSpam == 'yslnk' || $notSpam == 'yslnk' || $extraButton == 'yslnk')
201      $msg = array($passed_id);
202
203
204   // build list of checkboxes to be pre-selected when
205   // returning to message list
206   //
207   $prechecked = array();
208   if ($sb_reselect_messages)
209// could add the following, but not absolutely necessary
210//    && (empty($sb_report_spam_by_move_to_folder)
211//     || empty($sb_report_not_spam_by_move_to_folder)))
212   {
213      if (is_array($msg)) foreach ($msg as $messageID)
214         $prechecked[$messageID] = TRUE;
215   }
216
217
218
219   // if no messages were selected or spam buttons were not clicked on
220   // this request, just return and let SM handle the error, if any
221   //
222   if (empty($msg) || (empty($isSpam) && empty($notSpam) && empty($extraButton)))
223      return;
224
225
226   sq_change_text_domain('spam_buttons');
227
228
229
230   $note = '';
231   $success = FALSE;
232   $abort_message_view = FALSE;
233
234
235
236//TODO: if we implement "dont_wait" functionality, we can fork a child process here; then the child uses the reporting code below and exits, but the parent needs to skip to the section a few hundred lines down where it redirects back to the message list or read-message page ("DONE, WHERE DO WE RETURN TO?").  See the TODO section of the README file for some issues regarding this kind of functioality
237
238
239
240   // -----------------------------------------------------------------
241   //
242   // HANDLE EXTRA BUTTON CLICK
243   //
244
245
246   if (!empty($extraButton))
247   {
248      list($result, $note) = sb_custom_button_action($button_name, $callback, $msg, $passed_ent_id);
249
250
251      // what note do we use?  if we have success and there
252      // is a note configured in the config file, use it
253      //
254      if ($result)
255      {
256         if (!empty($custom_button_success_singular)
257          && !empty($custom_button_success_plural))
258            $note = ngettext($custom_button_success_singular, $custom_button_success_plural, count($msg));
259         else if (count($msg) < 2 && !empty($custom_button_success_singular))
260            $note = _($custom_button_success_singular);
261         else if (count($msg) > 1 && !empty($custom_button_success_plural))
262            $note = _($custom_button_success_plural);
263         else
264            $note = _($note);
265      }
266
267
268      // this should never actually be needed, but to be safe, let's
269      // make sure that none of the other action handlers below get
270      // kicked off...
271      //
272      $isSpam = NULL;
273      $notSpam = NULL;
274
275   }
276
277
278
279   // -----------------------------------------------------------------
280   //
281   // SPAM
282   //
283
284
285   // mark as spam!
286   //
287   if (!empty($isSpam))
288   {
289
290      // move-to-folder (only when target mailbox is not the same as source mailbox)
291      //
292      // note that we don't have to to check for $passed_ent_id because the report
293      // links/buttons are not shown when $passed_ent_id is non-zero, so we can never
294      // get here
295      //
296      global $mailbox;
297      if (!empty($sb_report_spam_by_move_to_folder)
298       && $mailbox != $sb_report_spam_by_move_to_folder
299       && is_array($msg))
300      {
301
302         global $auto_expunge, $imapConnection, $username, $key,
303                $imapServerAddress, $imapPort;
304         if (check_sm_version(1, 5, 2)) $key = FALSE;
305         if (!is_resource($imapConnection))
306            $imapConnection = sqimap_login($username, $key, $imapServerAddress, $imapPort, 0);
307
308         if (check_sm_version(1, 5, 2))
309         {
310            global $aMailbox;
311            sqGetGlobalVar('lastTargetMailbox', $lastTargetMailbox, SQ_SESSION);
312            spam_buttons_auto_create_folder($imapConnection, $sb_report_spam_by_move_to_folder);
313            if ($sb_report_spam_by_copy_to_folder)
314               $note = handleMessageListForm($imapConnection, $aMailbox, 'copy', $msg, $sb_report_spam_by_move_to_folder);
315            else
316               $note = handleMessageListForm($imapConnection, $aMailbox, 'move', $msg, $sb_report_spam_by_move_to_folder);
317            sqsession_register($lastTargetMailbox,'lastTargetMailbox');
318         }
319         else
320         {
321//TODO -- how to populate $note if an error occurs?  sqimap_msgs_list_copy() doesn't have a return value...
322            if ($sb_report_spam_by_copy_to_folder)
323               spam_buttons_sqimap_msgs_list_copy($imapConnection, $msg, $sb_report_spam_by_move_to_folder);
324            else
325               spam_buttons_sqimap_msgs_list_move($imapConnection, $msg, $sb_report_spam_by_move_to_folder);
326            if ($auto_expunge)
327               $cnt = sqimap_mailbox_expunge($imapConnection, $mailbox, true);
328            else
329               $cnt = 0;
330         }
331
332
333         // done reporting-by-move, now redirect user as needed
334         // right away if javascript is available and reporting
335         // from message view, or just prepare redirect location
336         // otherwise
337         //
338         if (empty($note))
339         {
340            $success = TRUE;
341            $note = _($reported_spam_text);
342//TODO? include something that identifies the message(s) that were reported(have to add it up in the loop above)?  might take too much screen real estate....?
343
344
345            global $javascript_on, $username, $mbx_response, $mailbox,
346                   $startMessage, $show_num, $sort, $imapConnection,
347                   $key, $imapServerAddress, $imapPort, $account;
348            $uri_args = 'mailbox=' . urlencode($mailbox)
349                      . (!empty($sort) ? "&sort=$sort" : '')
350                      . (!empty($account) ? "&account=$account" : '')
351                      . (!empty($startMessage) ? "&startMessage=$startMessage" : '');
352            if (check_sm_version(1, 5, 2)) $key = FALSE;
353            if (empty($mbx_response))
354            {
355               if (!is_resource($imapConnection))
356                  $imapConnection = sqimap_login($username, $key, $imapServerAddress, $imapPort, 0);
357               $mbx_response = sqimap_mailbox_select($imapConnection, $mailbox);
358            }
359
360
361            // when reading message itself, redirect back to
362            // message list after having moved it
363            //
364            if ($reporting_from_message_view && $javascript_on)
365            {
366
367//TODO: this may cause problems in 1.4.x, where output is probably already started
368               sqsession_register($note, 'sb_note');
369
370
371               // do we want to move to next message or return to message list?
372               //
373               global $redirect_location;
374               if ($move_to_message_after_report < 0)
375                  $redirect_location = sqm_baseuri()
376                                     . 'src/right_main.php?' . $uri_args;
377               else
378                  $redirect_location = sqm_baseuri()
379                                     . 'src/read_body.php?passed_id='
380                                     . $move_to_message_after_report . '&' . $uri_args;
381
382
383               // when viewing a message in the preview pane,
384               // need to clear pane (or go to next message)
385               // after delete as well as refresh message list
386               //
387               global $data_dir, $PHP_SELF;
388               if (is_plugin_enabled('preview_pane')
389                && getPref($data_dir, $username, 'use_previewPane', 0) == 1)
390               {
391
392                  global $request_refresh_message_list;
393                  $request_refresh_message_list = 1;
394
395                  // if not going to next message, go to empty preview pane
396                  //
397                  if ($move_to_message_after_report < 0)
398                     $redirect_location = sqm_baseuri() . 'plugins/preview_pane/empty_frame.php';
399
400
401                  // refresh message list & close
402                  //
403                  if (check_sm_version(1, 5, 2))
404                  {
405                     global $oTemplate;
406                     $oTemplate->assign('redirect_location', $redirect_location, FALSE);
407                     $oTemplate->assign('request_refresh_message_list', $request_refresh_message_list);
408                     $output = $oTemplate->fetch('plugins/spam_buttons/redirect_preview_pane.tpl');
409                     return array('read_body_header' => $output);
410                  }
411                  else
412                  {
413                     global $t;
414                     $t = array(); // no need to put config vars herein, they are already globalized
415                     include(SM_PATH . 'plugins/spam_buttons/templates/default/redirect_preview_pane.tpl');
416                  }
417
418               }
419
420
421               // otherwise, just redirect with javascript
422               //
423               else
424               {
425                  if (check_sm_version(1, 5, 2))
426                  {
427                     global $oTemplate;
428                     $oTemplate->assign('redirect_location', $redirect_location, FALSE);
429                     $output = $oTemplate->fetch('plugins/spam_buttons/redirect_standard.tpl');
430                     return array('read_body_header' => $output);
431                  }
432                  else
433                  {
434                     global $t;
435                     $t = array(); // no need to put config vars herein, they are already globalized
436                     include(SM_PATH . 'plugins/spam_buttons/templates/default/redirect_standard.tpl');
437                  }
438
439               }
440
441            }
442
443
444            // otherwise (reporting from message list or no javascript support),
445            // make sure we didn't move ourselves off the last page or anything
446            // like that (code copied from 1.4.11 src/move_messages.php)
447            //
448            else if (!$reporting_from_message_view)
449            {
450               if (($startMessage + $cnt - 1) >= $mbx_response['EXISTS'])
451               {
452                  if ($startMessage > $show_num)
453                     $location = set_url_var($location,'startMessage',$startMessage-$show_num, false);
454                  else
455                     $location = set_url_var($location,'startMessage',1, false);
456               }
457            }
458
459
460            // finally, if we don't have JavaScript and we moved the message
461            // out from under the message view, so we need to indicate that
462            // the current message view needs to be aborted
463            //
464            else if ($reporting_from_message_view && !$javascript_on)
465            {
466               $abort_message_view = TRUE;
467            }
468
469         }
470
471      }
472
473
474      // shell command
475      //
476      else if (!empty($is_spam_shell_command))
477      {
478
479         $note = report_by_shell_command($is_spam_shell_command, $msg, $passed_ent_id);
480
481         if (empty($note))
482         {
483            $success = TRUE;
484            $note = _($reported_spam_text);
485//TODO? include something that identifies the message(s) that were reported(have to add it up in the loop above)?  might take too much screen real estate....?
486         }
487
488      }
489
490
491      // re-send elsewhere via email
492      //
493      else if (!empty($is_spam_resend_destination))
494      {
495
496         $note = report_by_email($is_spam_resend_destination, $msg, $passed_ent_id, $is_spam_keep_copy_in_sent, $is_spam_subject_prefix);
497
498         if (empty($note))
499         {
500            $success = TRUE;
501            $note = _($reported_spam_text);
502//TODO? include something that identifies the message(s) that were reported(have to add it up in the loop above)?  might take too much screen real estate....?
503         }
504
505      }
506
507
508      // custom function callout
509      //
510      else if (!empty($sb_report_spam_by_custom_function))
511      {
512
513         $note = $sb_report_spam_by_custom_function($msg, $passed_ent_id);
514
515         if (empty($note))
516         {
517            $success = TRUE;
518            $note = _($reported_spam_text);
519//TODO? include something that identifies the message(s) that were reported(have to add it up in the loop above)?  might take too much screen real estate....?
520         }
521
522      }
523
524
525      else
526//TODO: we could put a warning here for the sysadmin... (but note that it is possible to get here when report-by-move-to-folder is correctly configured but no messages were selected by the user before pressing the report button)
527         $note = '';
528
529   }
530
531
532
533   // -----------------------------------------------------------------
534   //
535   // HAM
536   //
537
538
539   // mark as ham!
540   //
541   else if (!empty($notSpam))
542   {
543
544      // move-to-folder (only when target mailbox is not the same as source mailbox)
545      //
546      // note that we don't have to to check for $passed_ent_id because the report
547      // links/buttons are not shown when $passed_ent_id is non-zero, so we can never
548      // get here
549      //
550      global $mailbox;
551      if (!empty($sb_report_not_spam_by_move_to_folder)
552       && $mailbox != $sb_report_not_spam_by_move_to_folder
553       && is_array($msg))
554      {
555
556         global $auto_expunge, $imapConnection, $username, $key,
557                $imapServerAddress, $imapPort;
558         if (check_sm_version(1, 5, 2)) $key = FALSE;
559         if (!is_resource($imapConnection))
560            $imapConnection = sqimap_login($username, $key, $imapServerAddress, $imapPort, 0);
561
562         if (check_sm_version(1, 5, 2))
563         {
564            global $aMailbox;
565            sqGetGlobalVar('lastTargetMailbox', $lastTargetMailbox, SQ_SESSION);
566            spam_buttons_auto_create_folder($imapConnection, $sb_report_not_spam_by_move_to_folder);
567            if ($sb_report_not_spam_by_copy_to_folder)
568               $note = handleMessageListForm($imapConnection, $aMailbox, 'copy', $msg, $sb_report_not_spam_by_move_to_folder);
569            else
570               $note = handleMessageListForm($imapConnection, $aMailbox, 'move', $msg, $sb_report_not_spam_by_move_to_folder);
571            sqsession_register($lastTargetMailbox,'lastTargetMailbox');
572         }
573         else
574         {
575//TODO -- how to populate $note if an error occurs?  sqimap_msgs_list_copy() doesn't have a return value...
576            if ($sb_report_not_spam_by_copy_to_folder)
577               spam_buttons_sqimap_msgs_list_copy($imapConnection, $msg, $sb_report_not_spam_by_move_to_folder);
578            else
579               spam_buttons_sqimap_msgs_list_move($imapConnection, $msg, $sb_report_not_spam_by_move_to_folder);
580            if ($auto_expunge)
581               $cnt = sqimap_mailbox_expunge($imapConnection, $mailbox, true);
582            else
583               $cnt = 0;
584         }
585
586
587         // done reporting-by-move, now redirect user as needed
588         // right away if javascript is available and reporting
589         // from message view, or just prepare redirect location
590         // otherwise
591         //
592         if (empty($note))
593         {
594            $success = TRUE;
595            $note = _($reported_not_spam_text);
596//TODO? include something that identifies the message(s) that were reported(have to add it up in the loop above)?  might take too much screen real estate....?
597
598
599            global $javascript_on, $username, $mbx_response, $mailbox,
600                   $startMessage, $show_num, $sort, $imapConnection,
601                   $key, $imapServerAddress, $imapPort, $account;
602            $uri_args = 'mailbox=' . urlencode($mailbox)
603                      . (!empty($sort) ? "&sort=$sort" : '')
604                      . (!empty($account) ? "&account=$account" : '')
605                      . (!empty($startMessage) ? "&startMessage=$startMessage" : '');
606            if (check_sm_version(1, 5, 2)) $key = FALSE;
607            if (empty($mbx_response))
608            {
609               if (!is_resource($imapConnection))
610                  $imapConnection = sqimap_login($username, $key, $imapServerAddress, $imapPort, 0);
611               $mbx_response = sqimap_mailbox_select($imapConnection, $mailbox);
612            }
613
614
615            // when reading message itself, redirect back to
616            // message list after having moved it
617            //
618            if ($reporting_from_message_view && $javascript_on)
619            {
620
621//TODO: this may cause problems in 1.4.x, where output is probably already started
622               sqsession_register($note, 'sb_note');
623
624
625               // do we want to move to next message or return to message list?
626               //
627               global $redirect_location;
628               if ($move_to_message_after_report < 0)
629                  $redirect_location = sqm_baseuri()
630                                     . 'src/right_main.php?' . $uri_args;
631               else
632                  $redirect_location = sqm_baseuri()
633                                     . 'src/read_body.php?passed_id='
634                                     . $move_to_message_after_report . '&' . $uri_args;
635
636
637               // when viewing a message in the preview pane,
638               // need to clear pane (or go to next message)
639               // after delete as well as refresh message list
640               //
641               global $data_dir, $PHP_SELF;
642               if (is_plugin_enabled('preview_pane')
643                && getPref($data_dir, $username, 'use_previewPane', 0) == 1)
644               {
645
646                  global $request_refresh_message_list;
647                  $request_refresh_message_list = 1;
648
649                  // if not going to next message, go to empty preview pane
650                  //
651                  if ($move_to_message_after_report < 0)
652                     $redirect_location = sqm_baseuri() . 'plugins/preview_pane/empty_frame.php';
653
654
655                  // refresh message list & close
656                  //
657                  if (check_sm_version(1, 5, 2))
658                  {
659                     global $oTemplate;
660                     $oTemplate->assign('redirect_location', $redirect_location, FALSE);
661                     $oTemplate->assign('request_refresh_message_list', $request_refresh_message_list);
662                     $output = $oTemplate->fetch('plugins/spam_buttons/redirect_preview_pane.tpl');
663                     return array('read_body_header' => $output);
664                  }
665                  else
666                  {
667                     global $t;
668                     $t = array(); // no need to put config vars herein, they are already globalized
669                     include(SM_PATH . 'plugins/spam_buttons/templates/default/redirect_preview_pane.tpl');
670                  }
671
672               }
673
674
675               // otherwise, just redirect with javascript
676               //
677               else
678               {
679                  if (check_sm_version(1, 5, 2))
680                  {
681                     global $oTemplate;
682                     $oTemplate->assign('redirect_location', $redirect_location, FALSE);
683                     $output = $oTemplate->fetch('plugins/spam_buttons/redirect_standard.tpl');
684                     return array('read_body_header' => $output);
685                  }
686                  else
687                  {
688                     global $t;
689                     $t = array(); // no need to put config vars herein, they are already globalized
690                     include(SM_PATH . 'plugins/spam_buttons/templates/default/redirect_standard.tpl');
691                  }
692
693               }
694
695            }
696
697
698            // otherwise (reporting from message list or no javascript support),
699            // make sure we didn't move ourselves off the last page or anything
700            // like that (code copied from 1.4.11 src/move_messages.php)
701            //
702            else if (!$reporting_from_message_view)
703            {
704               if (($startMessage + $cnt - 1) >= $mbx_response['EXISTS'])
705               {
706                  if ($startMessage > $show_num)
707                     $location = set_url_var($location,'startMessage',$startMessage-$show_num, false);
708                  else
709                     $location = set_url_var($location,'startMessage',1, false);
710               }
711            }
712
713
714            // finally, if we don't have JavaScript and we moved the message
715            // out from under the message view, so we need to indicate that
716            // the current message view needs to be aborted
717            //
718            else if ($reporting_from_message_view && !$javascript_on)
719            {
720               $abort_message_view = TRUE;
721            }
722
723         }
724
725      }
726
727
728      // shell command
729      //
730      else if (!empty($is_not_spam_shell_command))
731      {
732
733         $note = report_by_shell_command($is_not_spam_shell_command, $msg, $passed_ent_id);
734
735
736         if (empty($note))
737         {
738            $success = TRUE;
739            $note = _($reported_not_spam_text);
740//TODO? include something that identifies the message(s) that were reported(have to add it up in the loop above)?  might take too much screen real estate....?
741         }
742
743      }
744
745
746      // re-send elsewhere via email
747      //
748      else if (!empty($is_not_spam_resend_destination))
749      {
750
751         $note = report_by_email($is_not_spam_resend_destination, $msg, $passed_ent_id, $is_not_spam_keep_copy_in_sent, $is_not_spam_subject_prefix);
752
753         if (empty($note))
754         {
755            $success = TRUE;
756            $note = _($reported_not_spam_text);
757//TODO? include something that identifies the message(s) that were reported(have to add it up in the loop above)?  might take too much screen real estate....?
758         }
759
760      }
761
762
763      // custom function callout
764      //
765      else if (!empty($sb_report_not_spam_by_custom_function))
766      {
767
768         $note = $sb_report_not_spam_by_custom_function($msg, $passed_ent_id);
769
770         if (empty($note))
771         {
772            $success = TRUE;
773            $note = _($reported_not_spam_text);
774//TODO? include something that identifies the message(s) that were reported(have to add it up in the loop above)?  might take too much screen real estate....?
775         }
776
777      }
778
779
780      else
781//TODO: we could put a warning here for the sysadmin... (but note that it is possible to get here when report-by-move-to-folder is correctly configured but no messages were selected by the user before pressing the report button)
782         $note = '';
783
784   }
785
786
787   sq_change_text_domain('squirrelmail');
788
789
790
791   // -----------------------------------------------------------------
792   //
793   // REPORTED... NOW MOVE?
794   //
795
796
797   // move spam
798   //
799   if ($success && !empty($isSpam) && $sb_move_after_report_spam
800    && (empty($sb_report_spam_by_move_to_folder)   // not if already moved!
801     || $sb_report_spam_by_copy_to_folder)
802    && empty($passed_ent_id)  // not if reporting an attachment!
803    && is_array($msg))
804   {
805
806      global $auto_expunge, $imapConnection, $username, $key, $show_num,
807             $mbx_response, $imapServerAddress, $imapPort, $mailbox,
808             $startMessage, $sort, $account, $javascript_on;
809      $uri_args = 'mailbox=' . urlencode($mailbox)
810                . (!empty($sort) ? "&sort=$sort" : '')
811                . (!empty($account) ? "&account=$account" : '')
812                . (!empty($startMessage) ? "&startMessage=$startMessage" : '');
813      if (check_sm_version(1, 5, 2)) $key = FALSE;
814      if (!is_resource($imapConnection))
815         $imapConnection = sqimap_login($username, $key, $imapServerAddress, $imapPort, 0);
816      if (empty($mbx_response))
817         $mbx_response = sqimap_mailbox_select($imapConnection, $mailbox);
818
819      // move messages only when target mailbox is not the same as source mailbox
820      //
821      if ($mailbox != $sb_move_after_report_spam)
822      {
823
824         if (check_sm_version(1, 5, 2))
825         {
826            global $aMailbox;
827            sqGetGlobalVar('lastTargetMailbox', $lastTargetMailbox, SQ_SESSION);
828            spam_buttons_auto_create_folder($imapConnection, $sb_move_after_report_spam);
829            if ($sb_copy_after_report_spam)
830               $move_result = handleMessageListForm($imapConnection, $aMailbox, 'copy', $msg, $sb_move_after_report_spam);
831            else
832               $move_result = handleMessageListForm($imapConnection, $aMailbox, 'move', $msg, $sb_move_after_report_spam);
833            sqsession_register($lastTargetMailbox,'lastTargetMailbox');
834         }
835         else
836         {
837            if ($sb_copy_after_report_spam)
838               spam_buttons_sqimap_msgs_list_copy($imapConnection, $msg, $sb_move_after_report_spam);
839            else
840               spam_buttons_sqimap_msgs_list_move($imapConnection, $msg, $sb_move_after_report_spam);
841            if ($auto_expunge)
842               $cnt = sqimap_mailbox_expunge($imapConnection, $mailbox, true);
843            else
844               $cnt = 0;
845         }
846
847
848         // when reading message itself, redirect back to
849         // message list after having moved it
850         //
851         if ($reporting_from_message_view && $javascript_on)
852         {
853
854//TODO: this may cause problems in 1.4.x, where output is probably already started
855            sqsession_register($note, 'sb_note');
856
857
858            // do we want to move to next message or return to message list?
859            //
860            global $redirect_location;
861            if ($move_to_message_after_report < 0)
862               $redirect_location = sqm_baseuri()
863                                  . 'src/right_main.php?' . $uri_args;
864            else
865               $redirect_location = sqm_baseuri()
866                                  . 'src/read_body.php?passed_id='
867                                  . $move_to_message_after_report . '&' . $uri_args;
868
869
870            // when viewing a message in the preview pane,
871            // need to clear pane (or go to next message)
872            // after delete as well as refresh message list
873            //
874            global $data_dir, $PHP_SELF;
875            if (is_plugin_enabled('preview_pane')
876             && getPref($data_dir, $username, 'use_previewPane', 0) == 1)
877            {
878
879               global $request_refresh_message_list;
880               $request_refresh_message_list = 1;
881
882               // if not going to next message, go to empty preview pane
883               //
884               if ($move_to_message_after_report < 0)
885                  $redirect_location = sqm_baseuri() . 'plugins/preview_pane/empty_frame.php';
886
887
888               // refresh message list & close
889               //
890               if (check_sm_version(1, 5, 2))
891               {
892                  global $oTemplate;
893                  $oTemplate->assign('redirect_location', $redirect_location, FALSE);
894                  $oTemplate->assign('request_refresh_message_list', $request_refresh_message_list);
895                  $output = $oTemplate->fetch('plugins/spam_buttons/redirect_preview_pane.tpl');
896                  return array('read_body_header' => $output);
897               }
898               else
899               {
900                  global $t;
901                  $t = array(); // no need to put config vars herein, they are already globalized
902                  include(SM_PATH . 'plugins/spam_buttons/templates/default/redirect_preview_pane.tpl');
903               }
904
905            }
906
907
908            // otherwise, just redirect with javascript
909            //
910            else
911            {
912               if (check_sm_version(1, 5, 2))
913               {
914                  global $oTemplate;
915                  $oTemplate->assign('redirect_location', $redirect_location, FALSE);
916                  $output = $oTemplate->fetch('plugins/spam_buttons/redirect_standard.tpl');
917                  return array('read_body_header' => $output);
918               }
919               else
920               {
921                  global $t;
922                  $t = array(); // no need to put config vars herein, they are already globalized
923                  include(SM_PATH . 'plugins/spam_buttons/templates/default/redirect_standard.tpl');
924               }
925
926            }
927
928         }
929
930
931         // otherwise (reporting from message list or no javascript support),
932         // make sure we didn't move ourselves off the last page or anything
933         // like that (code copied from 1.4.11 src/move_messages.php)
934         //
935         else if (!$reporting_from_message_view)
936         {
937            if (($startMessage + $cnt - 1) >= $mbx_response['EXISTS'])
938            {
939               if ($startMessage > $show_num)
940                  $location = set_url_var($location,'startMessage',$startMessage-$show_num, false);
941               else
942                  $location = set_url_var($location,'startMessage',1, false);
943            }
944         }
945
946
947         // finally, if we don't have JavaScript and we moved the message
948         // out from under the message view, so we need to indicate that
949         // the current message view needs to be aborted
950         //
951         else if ($reporting_from_message_view && !$javascript_on)
952         {
953            $abort_message_view = TRUE;
954         }
955
956      }
957
958   }
959
960
961   // move ham
962   //
963   if ($success && !empty($notSpam) && $sb_move_after_report_not_spam
964    && (empty($sb_report_not_spam_by_move_to_folder)   // not if already moved!
965     || $sb_report_not_spam_by_copy_to_folder)
966    && empty($passed_ent_id)  // not if reporting an attachment!
967    && is_array($msg))
968   {
969
970      global $auto_expunge, $imapConnection, $username, $key, $show_num,
971             $mbx_response, $imapServerAddress, $imapPort, $mailbox,
972             $startMessage, $sort, $account, $javascript_on;
973      $uri_args = 'mailbox=' . urlencode($mailbox)
974                . (!empty($sort) ? "&sort=$sort" : '')
975                . (!empty($account) ? "&account=$account" : '')
976                . (!empty($startMessage) ? "&startMessage=$startMessage" : '');
977      if (check_sm_version(1, 5, 2)) $key = FALSE;
978      if (!is_resource($imapConnection))
979         $imapConnection = sqimap_login($username, $key, $imapServerAddress, $imapPort, 0);
980      if (empty($mbx_response))
981         $mbx_response = sqimap_mailbox_select($imapConnection, $mailbox);
982
983      // move messages only when target mailbox is not the same as source mailbox
984      //
985      if ($mailbox != $sb_move_after_report_not_spam)
986      {
987
988         if (check_sm_version(1, 5, 2))
989         {
990            global $aMailbox;
991            sqGetGlobalVar('lastTargetMailbox', $lastTargetMailbox, SQ_SESSION);
992            spam_buttons_auto_create_folder($imapConnection, $sb_move_after_report_not_spam);
993            if ($sb_copy_after_report_not_spam)
994               $move_result = handleMessageListForm($imapConnection, $aMailbox, 'copy', $msg, $sb_move_after_report_not_spam);
995            else
996               $move_result = handleMessageListForm($imapConnection, $aMailbox, 'move', $msg, $sb_move_after_report_not_spam);
997            sqsession_register($lastTargetMailbox,'lastTargetMailbox');
998         }
999         else
1000         {
1001            if ($sb_copy_after_report_not_spam)
1002               spam_buttons_sqimap_msgs_list_copy($imapConnection, $msg, $sb_move_after_report_not_spam);
1003            else
1004               spam_buttons_sqimap_msgs_list_move($imapConnection, $msg, $sb_move_after_report_not_spam);
1005            if ($auto_expunge)
1006               $cnt = sqimap_mailbox_expunge($imapConnection, $mailbox, true);
1007            else
1008               $cnt = 0;
1009         }
1010
1011
1012         // when reading message itself, redirect back to
1013         // message list after having moved it
1014         //
1015         if ($reporting_from_message_view && $javascript_on)
1016         {
1017
1018//TODO: this may cause problems in 1.4.x, where output is probably already started
1019            sqsession_register($note, 'sb_note');
1020
1021
1022            // do we want to move to next message or return to message list?
1023            //
1024            global $redirect_location;
1025            if ($move_to_message_after_report < 0)
1026               $redirect_location = sqm_baseuri()
1027                                  . 'src/right_main.php?' . $uri_args;
1028            else
1029               $redirect_location = sqm_baseuri()
1030                                  . 'src/read_body.php?passed_id='
1031                                  . $move_to_message_after_report . '&' . $uri_args;
1032
1033
1034            // when viewing a message in the preview pane,
1035            // need to clear pane (or go to next message)
1036            // after delete as well as refresh message list
1037            //
1038            global $data_dir, $PHP_SELF;
1039            if (is_plugin_enabled('preview_pane')
1040             && getPref($data_dir, $username, 'use_previewPane', 0) == 1)
1041            {
1042
1043               global $request_refresh_message_list;
1044               $request_refresh_message_list = 1;
1045
1046               // if not going to next message, go to empty preview pane
1047               //
1048               if ($move_to_message_after_report < 0)
1049                  $redirect_location = sqm_baseuri() . 'plugins/preview_pane/empty_frame.php';
1050
1051
1052               // refresh message list & close
1053               //
1054               if (check_sm_version(1, 5, 2))
1055               {
1056                  global $oTemplate;
1057                  $oTemplate->assign('redirect_location', $redirect_location, FALSE);
1058                  $oTemplate->assign('request_refresh_message_list', $request_refresh_message_list);
1059                  $output = $oTemplate->fetch('plugins/spam_buttons/redirect_preview_pane.tpl');
1060                  return array('read_body_header' => $output);
1061               }
1062               else
1063               {
1064                  global $t;
1065                  $t = array(); // no need to put config vars herein, they are already globalized
1066                  include(SM_PATH . 'plugins/spam_buttons/templates/default/redirect_preview_pane.tpl');
1067               }
1068
1069            }
1070
1071
1072            // otherwise, just redirect with javascript
1073            //
1074            else
1075            {
1076               if (check_sm_version(1, 5, 2))
1077               {
1078                  global $oTemplate;
1079                  $oTemplate->assign('redirect_location', $redirect_location, FALSE);
1080                  $output = $oTemplate->fetch('plugins/spam_buttons/redirect_standard.tpl');
1081                  return array('read_body_header' => $output);
1082               }
1083               else
1084               {
1085                  global $t;
1086                  $t = array(); // no need to put config vars herein, they are already globalized
1087                  include(SM_PATH . 'plugins/spam_buttons/templates/default/redirect_standard.tpl');
1088               }
1089
1090            }
1091
1092         }
1093
1094
1095         // otherwise (reporting from message list or no javascript support),
1096         // make sure we didn't move ourselves off the last page or anything
1097         // like that (code copied from 1.4.11 src/move_messages.php)
1098         //
1099         else if (!$reporting_from_message_view)
1100         {
1101            if (($startMessage + $cnt - 1) >= $mbx_response['EXISTS'])
1102            {
1103               if ($startMessage > $show_num)
1104                  $location = set_url_var($location,'startMessage',$startMessage-$show_num, false);
1105               else
1106                  $location = set_url_var($location,'startMessage',1, false);
1107            }
1108         }
1109
1110
1111         // finally, if we don't have JavaScript and we moved the message
1112         // out from under the message view, so we need to indicate that
1113         // the current message view needs to be aborted
1114         //
1115         else if ($reporting_from_message_view && !$javascript_on)
1116         {
1117            $abort_message_view = TRUE;
1118         }
1119
1120      }
1121
1122   }
1123
1124
1125
1126   // -----------------------------------------------------------------
1127   //
1128   // OR DELETE?
1129   //
1130
1131
1132   // delete spam if needed (but not if already moved)
1133   //
1134   if ($success && $sb_delete_after_report && !empty($isSpam)
1135    && !$sb_move_after_report_spam  // not if already moved!
1136    && empty($passed_ent_id)  // not if reporting an attachment!
1137    && empty($sb_report_spam_by_move_to_folder))  // not if already moved!
1138   {
1139
1140      if (is_array($msg))
1141      {
1142         global $auto_expunge, $imapConnection, $username, $key, $show_num,
1143                $mbx_response, $imapServerAddress, $imapPort, $mailbox,
1144                $startMessage, $sort, $account, $javascript_on;
1145         $uri_args = 'mailbox=' . urlencode($mailbox)
1146                   . (!empty($sort) ? "&sort=$sort" : '')
1147                   . (!empty($account) ? "&account=$account" : '')
1148                   . (!empty($startMessage) ? "&startMessage=$startMessage" : '');
1149         if (check_sm_version(1, 5, 2)) $key = FALSE;
1150//LEFT OFF HERE -- debugging UW
1151//sm_print_r('$imapConnection contains:', $imapConnection);
1152//sqimap_logout($imapConnection);
1153         if (!is_resource($imapConnection))
1154            $imapConnection = sqimap_login($username, $key, $imapServerAddress, $imapPort, 0);
1155//echo '$mbx_response now contains:<br />';
1156//sm_print_r($mbx_response);
1157         if (empty($mbx_response))
1158//{
1159            $mbx_response = sqimap_mailbox_select($imapConnection, $mailbox);
1160//echo 'And now $mbx_response contains:<br />';
1161//sm_print_r($mbx_response);
1162//}
1163
1164         if (check_sm_version(1, 5, 2))
1165         {
1166            global $aMailbox;
1167            handleMessageListForm($imapConnection, $aMailbox, 'setDeleted', $msg);
1168         }
1169         else
1170         {
1171            sqimap_msgs_list_delete($imapConnection, $mailbox, $msg);
1172//echo "Finished deleting; now expunge if necessary...<br />";
1173            if ($auto_expunge)
1174            {
1175//echo "Expunging...<br />";
1176               $cnt = sqimap_mailbox_expunge($imapConnection, $mailbox, true);
1177            }
1178//echo "Finished<br />";
1179//exit;
1180         }
1181
1182
1183         // when reading message itself, redirect back to
1184         // message list after deletion
1185         //
1186         if ($reporting_from_message_view && $javascript_on)
1187         {
1188
1189//TODO: this may cause problems in 1.4.x, where output is probably already started
1190            sqsession_register($note, 'sb_note');
1191
1192
1193            // do we want to move to next message or return to message list?
1194            //
1195            global $redirect_location;
1196            if ($move_to_message_after_report < 0)
1197               $redirect_location = sqm_baseuri()
1198                                  . 'src/right_main.php?' . $uri_args;
1199            else
1200               $redirect_location = sqm_baseuri()
1201                                  . 'src/read_body.php?passed_id='
1202                                  . $move_to_message_after_report . '&' . $uri_args;
1203
1204
1205            // when viewing a message in the preview pane,
1206            // need to clear pane (or go to next message)
1207            // after delete as well as refresh message list
1208            //
1209            global $data_dir, $PHP_SELF;
1210            if (is_plugin_enabled('preview_pane')
1211             && getPref($data_dir, $username, 'use_previewPane', 0) == 1)
1212            {
1213
1214               global $request_refresh_message_list;
1215               $request_refresh_message_list = 1;
1216
1217               // if not going to next message, go to empty preview pane
1218               //
1219               if ($move_to_message_after_report < 0)
1220                  $redirect_location = sqm_baseuri() . 'plugins/preview_pane/empty_frame.php';
1221
1222
1223               // refresh message list & close
1224               //
1225               if (check_sm_version(1, 5, 2))
1226               {
1227                  global $oTemplate;
1228                  $oTemplate->assign('redirect_location', $redirect_location, FALSE);
1229                  $oTemplate->assign('request_refresh_message_list', $request_refresh_message_list);
1230                  $output = $oTemplate->fetch('plugins/spam_buttons/redirect_preview_pane.tpl');
1231                  return array('read_body_header' => $output);
1232               }
1233               else
1234               {
1235                  global $t;
1236                  $t = array(); // no need to put config vars herein, they are already globalized
1237                  include(SM_PATH . 'plugins/spam_buttons/templates/default/redirect_preview_pane.tpl');
1238               }
1239
1240            }
1241
1242
1243            // otherwise, just redirect with javascript
1244            //
1245            else
1246            {
1247               if (check_sm_version(1, 5, 2))
1248               {
1249                  global $oTemplate;
1250                  $oTemplate->assign('redirect_location', $redirect_location, FALSE);
1251                  $output = $oTemplate->fetch('plugins/spam_buttons/redirect_standard.tpl');
1252                  return array('read_body_header' => $output);
1253               }
1254               else
1255               {
1256                  global $t;
1257                  $t = array(); // no need to put config vars herein, they are already globalized
1258                  include(SM_PATH . 'plugins/spam_buttons/templates/default/redirect_standard.tpl');
1259               }
1260
1261            }
1262
1263         }
1264
1265
1266         // otherwise (reporting from message list or no javascript support),
1267         // make sure we didn't move ourselves off the last page or anything
1268         // like that (code copied from 1.4.11 src/move_messages.php)
1269         //
1270         else if (!$reporting_from_message_view)
1271         {
1272            if (($startMessage + $cnt - 1) >= $mbx_response['EXISTS'])
1273            {
1274               if ($startMessage > $show_num)
1275                  $location = set_url_var($location,'startMessage',$startMessage-$show_num, false);
1276               else
1277                  $location = set_url_var($location,'startMessage',1, false);
1278            }
1279         }
1280
1281
1282         // finally, if we don't have JavaScript and we moved the message
1283         // out from under the message view, so we need to indicate that
1284         // the current message view needs to be aborted
1285         //
1286         else if ($reporting_from_message_view && !$javascript_on)
1287         {
1288            $abort_message_view = TRUE;
1289         }
1290
1291      }
1292
1293   }
1294
1295
1296
1297   // -----------------------------------------------------------------
1298   //
1299   // DONE, WHERE DO WE RETURN TO?
1300   //
1301
1302
1303   // if no note, then we shouldn't do anything at all
1304   //
1305   if (empty($note))
1306   {
1307      if (check_sm_version(1, 5, 0))
1308         return;
1309      else
1310      {
1311         header('Location: ' . $location);
1312         exit;
1313      }
1314   }
1315
1316
1317   // when reading message itself, print message
1318   // in header and continue (unless message has been deleted)
1319   //
1320   if ($reporting_from_message_view)
1321   {
1322      if (check_sm_version(1, 5, 2))
1323         global $br;
1324      else
1325         $br = '<br />';
1326
1327      if ($abort_message_view)
1328         $note .= $br . _("The reported message is no longer available in this folder");
1329
1330      if (check_sm_version(1, 5, 2))
1331      {
1332         global $oTemplate;
1333         $oTemplate->assign('note', $note, FALSE); // FALSE because of use of $br
1334         $output = $oTemplate->fetch('plugins/spam_buttons/confirmation_note.tpl');
1335         return array('read_body_header' => $output);
1336         // note that message view will be aborted in next executed
1337         // template hook: template_construct_read_message_body.tpl
1338         // using the global $abort_message_view variable
1339      }
1340      else
1341      {
1342         echo html_tag('tr', html_tag('td', "<strong>$note</strong>", 'center', '', ' colspan="2"'));
1343
1344         // if we need to abort, do that now
1345         //
1346         if ($abort_message_view)
1347         {
1348            echo '</table></td></tr></table></body></html>';
1349            exit;
1350         }
1351
1352         return;
1353      }
1354   }
1355
1356
1357
1358   //
1359   // behavior is different when button on message list was clicked
1360   //
1361
1362
1363   // SM 1.5.2+: $note will be displayed automatically, so
1364   // all we need to do is return
1365   //
1366   if (check_sm_version(1, 5, 2))
1367   {
1368      global $preselected;
1369      $preselected = array_keys($prechecked);
1370      return;
1371   }
1372
1373
1374   // SM 1.5: just display note and let go
1375   //
1376   else if (check_sm_version(1, 5, 0))
1377   {
1378      global $preselected;
1379      $preselected = array_keys($prechecked);
1380      echo html_tag('div', '<b>' . $note .'</b>', 'center') . "<br />\n";
1381      return;
1382   }
1383
1384
1385   // For SM 1.4.x, redirect to message list so SM
1386   // doesn't try to do something else funny (1.4.x
1387   // assumes it has to delete messages... yikes)
1388   //
1389   else
1390   {
1391      // put note in session so we can display it when back in
1392      // message list, without putting $note in the location, since
1393      // it is hard to remove from there, even on subsequent requests
1394      //
1395      sqsession_register($note, 'sb_note');
1396
1397      // compress prechecked array and pass it along
1398      //
1399      $query = '';
1400      foreach ($prechecked as $msgid => $ignore)
1401         $query .= '&preselected[' . $msgid . ']=1';
1402      if (strpos($location, '?') === FALSE)
1403         $query{0} = '?';
1404
1405      //header('Location: ' . $location . $query . '&note=' . urlencode($note));
1406      header('Location: ' . $location . $query);
1407      exit;
1408   }
1409
1410
1411}
1412
1413
1414
1415/**
1416  * Reports one or more spam/non-spam using email redirection.
1417  *
1418  * @param string  $destination       The email address to which the
1419  *                                   message should be redirected.
1420  * @param array   $msg               An array of message IDs to be reported.
1421  * @param string  $passed_ent_id     The message entity being reported
1422  *                                   (zero if the message itself is being
1423  *                                   reported (only applicable when there
1424  *                                   is just one element in the $msg array))
1425  * @param boolean $keep_copy_in_sent When sending as an attachment,
1426  *                                   should a copy of the spam report
1427  *                                   being sent out get stored in the
1428  *                                   user's sent folder?
1429  * @param string  $subjectPrefix     Any extra subject info for
1430  *                                   redirected mail's subject.
1431  *                                   (optional; default is empty
1432  *                                   string, nothing is done to subject)
1433  *
1434  * @return string An error message if an error occurred,
1435  *                empty string otherwise
1436  *
1437  */
1438function report_by_email($destination, $msg, $passed_ent_id,
1439                         $keep_copy_in_sent, $subjectPrefix='')
1440{
1441
1442   global $spam_report_email_method, $spam_report_smtpServerAddress,
1443          $spam_report_smtpPort, $spam_report_useSendmail,
1444          $spam_report_smtp_auth_mech, $spam_report_use_smtp_tls,
1445          $smtpServerAddress, $smtpPort, $useSendmail, $smtp_auth_mech,
1446          $use_smtp_tls, $sb_debug, $data_dir, $username, $domain;
1447   $at_sign = '@';
1448
1449   spam_buttons_init();
1450
1451
1452   // do replacements on destination
1453   //
1454   if (strpos($username, $at_sign) !== FALSE)
1455      list($user, $dom) = explode($at_sign, $username);
1456   else
1457   {
1458      $user = $username;
1459      $dom = $domain;
1460   }
1461   $email_address = getPref($data_dir, $username, 'email_address');
1462   $destination = str_replace(array('###EMAIL_PREF###', '###EMAIL_ADDRESS###', '###USERNAME###', '###DOMAIN###'),
1463                              array($email_address, $user . $at_sign . $dom, $user, $dom),
1464                              $destination);
1465
1466
1467   // take care of overrides for SMTP server
1468   //
1469   if (!empty($spam_report_smtpServerAddress))
1470      $smtpServerAddress = $spam_report_smtpServerAddress;
1471   if (!empty($spam_report_smtpPort))
1472      $smtpPort = $spam_report_smtpPort;
1473   if ($spam_report_useSendmail !== '')
1474      if (strtolower($spam_report_useSendmail) === 'false')
1475         $useSendmail = FALSE;
1476      else
1477         $useSendmail = $spam_report_useSendmail;
1478   if (!empty($spam_report_smtp_auth_mech))
1479      $smtp_auth_mech = $spam_report_smtp_auth_mech;
1480   if (!empty($spam_report_use_smtp_tls))
1481      $use_smtp_tls = $spam_report_use_smtp_tls;
1482
1483
1484   $note = '';
1485
1486
1487   // redirect by bouncing message and preserving headers
1488   //
1489   if ($spam_report_email_method == 'bounce')
1490   {
1491
1492      global $imapServerAddress, $imapPort, $useSendmail;
1493
1494
1495      // we will be manually manipulating $_GET, so...
1496      //
1497      global $_GET;
1498      if (!check_php_version(4,1))
1499      {
1500         global $HTTP_GET_VARS;
1501         $_GET = $HTTP_GET_VARS;
1502      }
1503
1504
1505      if (is_array($msg)) foreach ($msg as $messageID)
1506      {
1507         $_GET['bounce_send_to'] = $destination;
1508         $_GET['passed_id'] = $messageID;
1509         $_GET['passed_ent_id'] = $passed_ent_id;
1510         require(SM_PATH . 'plugins/spam_buttons/bounce_send.php');
1511      }
1512
1513   }
1514
1515
1516   // redirect by including message as an attachment
1517   //
1518   else
1519   {
1520
1521      // some versions of SM need this when using some compose functions
1522      //
1523      if (!function_exists('addressbook_init'))
1524         include_once(SM_PATH . 'functions/addressbook.php');
1525
1526      sqGetGlobalVar('mailbox', $mailbox);
1527      if (check_sm_version(1, 5, 2))
1528         include_once(SM_PATH . 'plugins/spam_buttons/compose_functions-1.5.2.php');
1529      else if (check_sm_version(1, 4, 14))
1530         include_once(SM_PATH . 'plugins/spam_buttons/compose_functions-1.4.14.php');
1531      else if (check_sm_version(1, 4, 11))
1532         include_once(SM_PATH . 'plugins/spam_buttons/compose_functions-1.4.11.php');
1533      else
1534         include_once(SM_PATH . 'plugins/spam_buttons/compose_functions-1.4.10.php');
1535
1536
1537      if (is_array($msg)) foreach ($msg as $messageID)
1538      {
1539
1540         global $composeMessage, $send_to, $subject, $sb_keep_copy_in_sent;
1541
1542         $sb_keep_copy_in_sent = $keep_copy_in_sent;
1543
1544         $composeMessage = new Message();
1545         $rfc822_header = new Rfc822Header();
1546         $composeMessage->rfc822_header = $rfc822_header;
1547         $composeMessage->reply_rfc822_header = '';
1548
1549         $message = newMail($mailbox, $messageID, $passed_ent_id, 'forward_as_attachment', '');
1550         $subject = $message['subject'];
1551         if (!empty($subjectPrefix))
1552            $subject = preg_replace('/fwd/i', $subjectPrefix, $subject);
1553
1554         $send_to = $destination;
1555
1556         $Result = deliverMessage($composeMessage);
1557         if (! $Result)
1558         {
1559            sq_change_text_domain('spam_buttons');
1560            $note = _("ERROR: Report could not be delivered");
1561            sq_change_text_domain('squirrelmail');
1562            break;
1563         }
1564
1565         // dump stuff out if debugging
1566         //
1567         if ($sb_debug)
1568         {
1569            echo '<hr /><strong>EMAIL ADDRESS USED TO REPORT:</strong> ' . $destination . '<br /><br />';
1570            echo '<hr /><strong>MESSAGE BODY AS REPORTED:</strong> (note that this is a parsed representation thereof)';
1571            sm_print_r($composeMessage);
1572            echo '<br /><br />';
1573            exit;
1574         }
1575
1576      }
1577
1578   }
1579
1580
1581   return $note;
1582
1583}
1584
1585
1586
1587/**
1588  * Reports one or more spam/non-spam using the shell
1589  * command provided.
1590  *
1591  * @param string $command       The shell command to be used.
1592  * @param array  $msg           An array of message IDs to be reported.
1593  * @param string $passed_ent_id The message entity being reported
1594  *                              (zero if the message itself is being
1595  *                              reported (only applicable when there
1596  *                              is just one element in the $msg array))
1597  *
1598  * @return string An error message if an error occurred,
1599  *                empty string otherwise
1600  *
1601  */
1602function report_by_shell_command($command, $msg, $passed_ent_id)
1603{
1604
1605   global $attachment_dir, $data_dir, $username, $domain, $sb_debug;
1606   $at_sign = '@';
1607
1608   spam_buttons_init();
1609
1610
1611   $passed_ent_id = 0;
1612   sqGetGlobalVar('passed_ent_id',   $passed_ent_id,  SQ_FORM);
1613   sqGetGlobalVar('mailbox', $mailbox);
1614
1615
1616   // do replacements on command
1617   //
1618   if (strpos($username, $at_sign) !== FALSE)
1619      list($user, $dom) = explode($at_sign, $username);
1620   else
1621   {
1622      $user = $username;
1623      $dom = $domain;
1624   }
1625   $email_address = getPref($data_dir, $username, 'email_address');
1626   $command = str_replace(array('###EMAIL_PREF###', '###EMAIL_ADDRESS###', '###USERNAME###', '###DOMAIN###'),
1627                          array($email_address, $user . $at_sign . $dom, $user, $dom),
1628                          $command);
1629
1630
1631   $note = '';
1632   $timestamp = time();
1633
1634
1635   if (is_array($msg)) foreach ($msg as $messageID)
1636   {
1637
1638      // get message body, correctly formatted
1639      //
1640      global $uid_support, $imapConnection, $username, $key,
1641             $mbx_response, $imapServerAddress, $imapPort, $mailbox;
1642      if (check_sm_version(1, 5, 2)) { $key = FALSE; $uid_support = TRUE; }
1643
1644      if (!is_resource($imapConnection))
1645         $imapConnection = sqimap_login($username, $key, $imapServerAddress, $imapPort, 0);
1646      if (empty($mbx_response))
1647         $mbx_response = sqimap_mailbox_select($imapConnection, $mailbox);
1648      $response = '';
1649      $message = '';
1650
1651      if (empty($passed_ent_id))
1652         $raw_message = sqimap_run_command($imapConnection, "FETCH $messageID BODY.PEEK[]", true, $response, $message, $uid_support);
1653      else
1654         $raw_message = sqimap_run_command($imapConnection, "FETCH $messageID BODY.PEEK[$passed_ent_id]", true, $response, $message, $uid_support);
1655
1656      if ($response != 'OK')
1657      {
1658         global $color;
1659         sq_change_text_domain('spam_buttons');
1660         $msg = sprintf(_("Could not find requested message: %s"), $message);
1661         sq_change_text_domain('squirrelmail');
1662         $ret = plain_error_message($msg, $color);
1663         if (check_sm_version (1, 5, 2))
1664         {
1665            echo $ret;
1666            global $oTemplate;
1667            $oTemplate->display('footer.tpl');
1668         }
1669         exit;
1670      }
1671
1672      // rebuild the message exactly as it comes from the IMAP server
1673      // (except first and last array entries are command wrappers, so skip them)
1674      //
1675      array_shift($raw_message);
1676      array_pop($raw_message);
1677      $raw_message = implode('', $raw_message);
1678
1679
1680      // store message in attachments directory in temp file
1681      //
1682      $tempFile = $attachment_dir . '/sb_tmp_' . $messageID . '_' . $timestamp;
1683      $tempFileOK = FALSE;
1684      if ($FILE = @fopen($tempFile, 'w'))
1685      {
1686
1687         fwrite($FILE, $raw_message);
1688         fclose($FILE);
1689         $tempFileOK = TRUE;
1690
1691
1692         // run command
1693         //
1694         $cmd = $command . ' < ' . $tempFile;
1695//sm_print_r($cmd, $raw_message);exit;
1696         $lastLineOfOutput = exec($cmd, $allOutput, $retValue);
1697//sm_print_r($allOutput);exit;
1698
1699
1700         // remove temp file
1701         //
1702         unlink($tempFile);
1703
1704
1705         // dump stuff out if debugging
1706         //
1707         if ($sb_debug)
1708         {
1709            echo '<hr /><strong>COMMAND USED TO REPORT:</strong> ' . $cmd . '<br /><br />';
1710            echo '<hr /><strong>MESSAGE BODY AS REPORTED:</strong> ';
1711            sm_print_r($raw_message);
1712            echo '<br /><br />';
1713            echo '<hr /><strong>RESULTS FROM REPORT:</strong> (' . $retValue . ')';
1714            sm_print_r($allOutput);
1715            echo '<br /><br />';
1716            exit;
1717         }
1718
1719      }
1720
1721
1722      // couldn't open temp file
1723      //
1724      if (!$tempFileOK)
1725      {
1726         $note = _("ERROR: Could not open temp file; check attachments directory permissions");
1727         break;
1728      }
1729
1730
1731      // oops, command failed
1732      //
1733      else if ($retValue !== 0)
1734      {
1735         if (empty($passed_ent_id))
1736            $note = str_replace(array('%1', '%2', '%3'),
1737                                array($retValue, $messageID, $lastLineOfOutput),
1738                                _("ERROR %1: Problem reporting message ID %2: %3"));
1739         else
1740            $note = str_replace(array('%1', '%2', '%3', '%4'),
1741                                array($retValue, $messageID, $lastLineOfOutput, $passed_ent_id),
1742                                _("ERROR %1: Problem reporting message ID %2 (entity %4): %3"));
1743         break;
1744      }
1745
1746   }
1747
1748   return $note;
1749
1750}
1751
1752
1753
1754/**
1755  * Abort message view when message is moved/deleted
1756  * out from under current message view (SM 1.5.2+ only)
1757  *
1758  */
1759function sb_abort_message_view_do()
1760{
1761
1762   global $abort_message_view;
1763
1764   if ($abort_message_view)
1765   {
1766      global $oTemplate;
1767      $oTemplate->display('footer.tpl');
1768      exit;
1769   }
1770
1771}
1772
1773
1774
1775//
1776// ripped from functions/auth.php (merged both STABLE and DEVEL;
1777// the only difference being how the hook is handled)
1778//
1779
1780/**
1781 * Fillin user and password based on SMTP auth settings.
1782 *
1783 * @param string $user Reference to SMTP username
1784 * @param string $pass Reference to SMTP password (unencrypted)
1785 */
1786if (!function_exists('get_smtp_user'))
1787{
1788function get_smtp_user(&$user, &$pass) {
1789    global $username, $smtp_auth_mech,
1790           $smtp_sitewide_user, $smtp_sitewide_pass;
1791
1792    if ($smtp_auth_mech == 'none') {
1793        $user = '';
1794        $pass = '';
1795    } elseif ( isset($smtp_sitewide_user) && isset($smtp_sitewide_pass) &&
1796               !empty($smtp_sitewide_user)) {
1797        $user = $smtp_sitewide_user;
1798        $pass = $smtp_sitewide_pass;
1799    } else {
1800        $user = $username;
1801        $pass = sqauth_read_password();
1802    }
1803
1804    if (check_sm_version(1, 5, 2)) {
1805        $temp = array(&$user, &$pass);
1806        do_hook('smtp_auth', $temp);
1807    } else {
1808        $ret = do_hook_function('smtp_auth', array($user, $pass));
1809        if (!empty($ret[0]))
1810            $user = $ret[0];
1811        if (!empty($ret[1]))
1812            $pass = $ret[1];
1813    }
1814}
1815}
1816
1817
1818
1819// findPreviousMessage()'s prototype changed as of 1.5.1
1820//
1821function spam_buttons_findPreviousMessage($passed_id)
1822{
1823   if (check_sm_version(1, 5, 1))
1824   {
1825      if (!sqGetGlobalVar('what', $what, SQ_GET)) $what = 0;
1826      global $aMailbox;
1827      return findPreviousMessage($aMailbox['UIDSET'][$what], $passed_id);
1828   }
1829   else
1830   {
1831      global $mbx_response;
1832      if (empty($mbx_response))
1833      {
1834         global $imapConnection, $mailbox, $key, $username,
1835                $imapServerAddress, $imapPort;
1836         if (!is_resource($imapConnection))
1837            $imapConnection = sqimap_login($username, $key, $imapServerAddress, $imapPort, 0);
1838         $mbx_response = sqimap_mailbox_select($imapConnection, $mailbox);
1839      }
1840      return findPreviousMessage($mbx_response['EXISTS'], $passed_id);
1841   }
1842}
1843
1844
1845
1846// findNextMessage()'s prototype changed as of 1.5.1
1847//
1848function spam_buttons_findNextMessage($passed_id)
1849{
1850   if (check_sm_version(1, 5, 1))
1851   {
1852      if (!sqGetGlobalVar('what', $what, SQ_GET)) $what = 0;
1853      global $aMailbox;
1854      return findNextMessage($aMailbox['UIDSET'][$what], $passed_id);
1855   }
1856   else
1857      return findNextMessage($passed_id);
1858}
1859
1860
1861
1862// The move and copy function names change as of 1.4.18 to be what
1863// they say they are, so use those if we are at the right version.
1864//
1865// For versions less than 1.4.18, there is no copy function, so we
1866// use a modified version of the move function from 1.4.11 (which,
1867// ironically is mis-labelled "copy")
1868//
1869// Also, if configured to do so, the target folder will be created
1870// first if it does not exist.
1871//
1872function spam_buttons_sqimap_msgs_list_copy($imap_stream, $id, $mailbox) {
1873
1874   spam_buttons_auto_create_folder($imap_stream, $mailbox);
1875
1876
1877   if (check_sm_version(1, 4, 18))
1878      return sqimap_msgs_list_copy($imap_stream, $id, $mailbox);
1879
1880
1881   // here is our own modified version of 1.4.11's move ("copy") function...
1882   //
1883   global $uid_support;
1884   $msgs_id = sqimap_message_list_squisher($id);
1885   $read = sqimap_run_command ($imap_stream, "COPY $msgs_id \"$mailbox\"", true, $response, $message, $uid_support);
1886   if ($response == 'OK')
1887      return true;
1888   else
1889      return false;
1890
1891}
1892
1893
1894
1895// the move and copy function names change as of 1.4.18 to be what they say they are
1896//
1897// Also, if configured to do so, the target folder will be created
1898// first if it does not exist.
1899//
1900function spam_buttons_sqimap_msgs_list_move($imap_stream, $id, $mailbox) {
1901
1902   spam_buttons_auto_create_folder($imap_stream, $mailbox);
1903
1904
1905   if (check_sm_version(1, 4, 18))
1906      return sqimap_msgs_list_move($imap_stream, $id, $mailbox);
1907
1908
1909   // mis-labelled function name in versions less than 1.4.18
1910   //
1911   return sqimap_msgs_list_copy($imap_stream, $id, $mailbox);
1912
1913}
1914
1915
1916
1917// create a folder if it does not exist if necessary
1918//
1919function spam_buttons_auto_create_folder($imap_stream, $mailbox)
1920{
1921
1922   // auto-create non-existing folder?
1923   //
1924   global $sb_auto_create_destination_folder; // assume config file already globally included
1925   if ($sb_auto_create_destination_folder
1926    && !sqimap_mailbox_exists($imap_stream, $mailbox))
1927      sqimap_mailbox_create($imap_stream, $mailbox, '');
1928
1929}
1930
1931
1932
1933/**
1934  * Execute action for custom button click.
1935  *
1936  * @param string $button_name    The name of the button or link
1937  *                               (with non-alphanumerics having
1938  *                               been replaced with underscores).
1939  * @param string $callback       The name of the function that
1940  *                               will handle the button action.
1941  * @param array  $messages       A list of message IDs.
1942  * @param string $passed_ent_id  Entity ID when message is an
1943  *                               attachment (might be empty).
1944  *
1945  * @return array A two-element array, the first element being
1946  *               a boolean value that is TRUE if all message(s)
1947  *               were processed normally and FALSE if some error
1948  *               occured.  The second element is a string containing
1949  *               a note (untranslated) that will be displayed to
1950  *               the user upon completion (may be blank, in which
1951  *               case, any message from the user configuration will
1952  *               be used if available).
1953  *
1954  */
1955function sb_custom_button_action($button_name, $callback, $messages, $passed_ent_id)
1956{
1957
1958   global $username;
1959   $result = array(FALSE, 'ERROR: Unknown error');
1960
1961
1962   // first, make sure the callback is correctly configured
1963   //
1964   if (empty($callback) || !function_exists($callback))
1965   {
1966      global $color;
1967
1968      // if users complain of seeing a message "Function  not found in
1969      // Spam Buttons plugin", it means they don't have a action callback
1970      // defined at all
1971      //
1972      sq_change_text_domain('spam_buttons');
1973      $msg = sprintf(_("Function %s not found in Spam Buttons plugin"), $callback);
1974      sq_change_text_domain('squirrelmail');
1975      $ret = plain_error_message($msg, $color);
1976      if (check_sm_version (1, 5, 2))
1977      {
1978         echo $ret;
1979         global $oTemplate;
1980         $oTemplate->display('footer.tpl');
1981      }
1982      exit;
1983   }
1984
1985
1986   // loop through each message (even if there is just one)
1987   //
1988   foreach ($messages as $message_id)
1989   {
1990
1991      // this retrieves the message's From header in the format
1992      // array(0 => 'From:', 1 => '"Jose" <jose@example.org>')
1993      //
1994      $from = sb_get_message_header($message_id, $passed_ent_id, 'From');
1995
1996
1997      // this parses out just the email address portion of the From header
1998      //
1999      if (function_exists('parseRFC822Address'))
2000      {
2001         $from = parseRFC822Address($from[1], 1);
2002         $from = $from[0][2] . '@' . $from[0][3];
2003      }
2004      else
2005      {
2006         $from = parseAddress($from[1], 1);
2007         $from = $from[0][0];
2008      }
2009
2010
2011      // execute the callback
2012      //
2013      $result = $callback($button_name, $username, $from, $message_id, $passed_ent_id);
2014
2015      if (!is_array($result)) $result = array($result, '');
2016
2017      if (!$result[0])
2018         return array(FALSE, 'ERROR: ' . $result[1]);
2019
2020   }
2021
2022
2023   // finished, just return success (which will be the last known
2024   // value of $result... any note therein will also be used)
2025   //
2026   return $result;
2027
2028}
2029
2030
2031
2032