fsf changes, meant to be rebased on upstream master
authorIan Kelling <iank@fsf.org>
Mon, 27 Apr 2020 01:39:19 +0000 (21:39 -0400)
committerroot <root@mail.fsf.org>
Thu, 26 May 2022 18:48:08 +0000 (18:48 +0000)
As upstream changes, rebase this commit on top.

The change to read_body.php, documented here
https://sourceforge.net/p/squirrelmail/mailman/message/36992407/
copied here in case that link dies:

In the svn version, when viewing a message, if you click the move or
copy button, the page changes to the list of messages. In older versions
such as 1.4.13, that button was enabled by the delete_move_next plugin,
and when pressing move, the page would change to the next message. That
is clearly the way it should work. When using the preview panel, this
behavior especially makes no sense because you were already seeing the
message list and it just turns the preview panel into blank space.

After a quick look into the code, I was able to make a one line change
to the svn version so that the the page does not change at all when
pressing move, which helps workaround the problem so that I can then
press a key to go to the next message. I'm hoping someone here is
familiar with the code and can help identify the root cause and find a
proper fix so it goes to the next message.

Here is a comparison of the post request when clicking move in svn vs
old working 1.4.13:

SVN post:

https://webmail.fsf.org/src/read_body.php?mailbox=INBOX&sort=6&startMessage=1&passed_id=18
form data:
show_more "0"
move_id "19"
targetMailbox "INBOX.Trash"

Working 1.4.13 post:

https://mail1p.fsf.org/src/right_main.php
form data:
smtoken "EEZR1hS4cPUh"
mailbox "INBOX"
msg[0] "19"
targetMailbox "INBOX.Trash"
moveButton "Move"

I figured out that if the post url didn't have any path, or had a path
of "right_main.php", like the old version, it would stop changing the
page, and there was already an example in the code of not passing the
path, so I copied that to make this hacky patch.

I enabled level 2 debug mode, didnt result in any output in the logs.

Configtest shows no errors.

12 files changed:
class/deliver/Deliver.class.php
class/deliver/Deliver_SMTP.class.php
functions/db_prefs.php
functions/imap_general.php
functions/imap_messages.php
functions/mime.php
functions/page_header.php
images/fsf.png [new file with mode: 0644]
include/load_prefs.php
include/options/folder.php
plugins/squirrelspell/sqspell_config.php
src/read_body.php

index 403b88f..258360e 100644 (file)
@@ -741,7 +741,7 @@ class Deliver {
             /* RFC 2298 */
             $header[] = 'Disposition-Notification-To: '.$dnt. $rn;
         }
-        if ($rfc822_header->dsn) {
+        if (isset($rfc822_header->dsn) && $rfc822_header->dsn) {
             $dsn = $rfc822_header->getAddr_s('dsn');
             $header[] = 'Return-Receipt-To: '.$dsn. $rn;
         }
index 90075cc..6029acb 100644 (file)
@@ -347,7 +347,8 @@ class Deliver_SMTP extends Deliver {
             if (!$to[$i]->host) $to[$i]->host = $domain;
             if (strlen($to[$i]->mailbox)) {
                 // Ask for DSN if user has requested such and remote server supports it
-                if ($rfc822_header->dsn && array_key_exists('DSN',$this->ehlo)) {
+                if (isset($rfc822_header->dsn) && $rfc822_header->dsn
+                 && array_key_exists('DSN',$this->ehlo)) {
                     // TODO: Make the DSN parameters configurable by admin? user?
                     fputs($stream, 'RCPT TO:<'.$to[$i]->mailbox.'@'.$to[$i]->host."> NOTIFY=SUCCESS,DELAY,FAILURE\r\n");
                     // Retry without DSN fields for cranky MTAs
@@ -368,7 +369,8 @@ class Deliver_SMTP extends Deliver {
             if (!$cc[$i]->host) $cc[$i]->host = $domain;
             if (strlen($cc[$i]->mailbox)) {
                 // Ask for DSN if user has requested such and remote server supports it
-                if ($rfc822_header->dsn && array_key_exists('DSN',$this->ehlo)) {
+                if (isset($rfc822_header->dsn) && $rfc822_header->dsn
+                 && array_key_exists('DSN',$this->ehlo)) {
                     // TODO: Make the DSN parameters configurable by admin? user?
                     fputs($stream, 'RCPT TO:<'.$cc[$i]->mailbox.'@'.$cc[$i]->host."> NOTIFY=SUCCESS,DELAY,FAILURE\r\n");
                     // Retry without DSN fields for cranky MTAs
@@ -389,7 +391,8 @@ class Deliver_SMTP extends Deliver {
             if (!$bcc[$i]->host) $bcc[$i]->host = $domain;
             if (strlen($bcc[$i]->mailbox)) {
                 // Ask for DSN if user has requested such and remote server supports it
-                if ($rfc822_header->dsn && array_key_exists('DSN',$this->ehlo)) {
+                if (isset($rfc822_header->dsn) && $rfc822_header->dsn
+                 && array_key_exists('DSN',$this->ehlo)) {
                     // TODO: Make the DSN parameters configurable by admin? user?
                     fputs($stream, 'RCPT TO:<'.$bcc[$i]->mailbox.'@'.$bcc[$i]->host."> NOTIFY=SUCCESS,DELAY,FAILURE\r\n");
                     // Retry without DSN fields for cranky MTAs
index a5123dd..b153450 100644 (file)
  *                                 internal database information from being
  *                                 exposed. This should be enabled only for
  *                                 debugging purposes.
- *    string $pdo_identifier_quote_char By default, SquirrelMail will quote
- *                                      table and field names in database
- *                                      queries with what it thinks is the
- *                                      appropriate quote character for the
- *                                      database type being used (backtick
- *                                      for MySQL (and thus MariaDB), double
- *                                      quotes for all others), but you can
- *                                      override the character used by
- *                                      putting it here, or tell SquirrelMail
- *                                      NOT to quote identifiers by setting
- *                                      this to "none"
+ *    string $db_identifier_quote_char By default, SquirrelMail will quote
+ *                                     table and field names in database
+ *                                     queries with what it thinks is the
+ *                                     appropriate quote character for the
+ *                                     database type being used (backtick
+ *                                     for MySQL (and thus MariaDB), double
+ *                                     quotes for all others), but you can
+ *                                     override the character used by
+ *                                     putting it here, or tell SquirrelMail
+ *                                     NOT to quote identifiers by setting
+ *                                     this to "none"
  *
  * @copyright 1999-2022 The SquirrelMail Project Team
  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
@@ -245,7 +245,7 @@ class dbPrefs {
      *
      */
     function open() {
-        global $prefs_dsn, $prefs_table, $use_pdo, $pdo_identifier_quote_char;
+        global $prefs_dsn, $prefs_table, $use_pdo, $db_identifier_quote_char;
         global $prefs_user_field, $prefs_key_field, $prefs_val_field;
         global $prefs_user_size, $prefs_key_size, $prefs_val_size;
 
@@ -268,16 +268,16 @@ class dbPrefs {
             $this->db_type = SMDB_PGSQL;
         }
 
-        // figure out identifier quoting (only used for PDO, though we could change that)
-        if (empty($pdo_identifier_quote_char)) {
+        // figure out identifier quoting
+        if (empty($db_identifier_quote_char)) {
             if ($this->db_type == SMDB_MYSQL)
                 $this->identifier_quote_char = '`';
             else
                 $this->identifier_quote_char = '"';
-        } else if ($pdo_identifier_quote_char === 'none')
+        } else if ($db_identifier_quote_char === 'none')
             $this->identifier_quote_char = '';
         else
-            $this->identifier_quote_char = $pdo_identifier_quote_char;
+            $this->identifier_quote_char = $db_identifier_quote_char;
 
         if (!empty($prefs_table)) {
             $this->table = $prefs_table;
@@ -285,14 +285,6 @@ class dbPrefs {
         if (!empty($prefs_user_field)) {
             $this->user_field = $prefs_user_field;
         }
-
-        // the default user field is "user", which in PostgreSQL
-        // is an identifier and causes errors if not escaped
-        //
-        if ($this->db_type == SMDB_PGSQL) {
-           $this->user_field = '"' . $this->user_field . '"';
-        }
-
         if (!empty($prefs_key_field)) {
             $this->key_field = $prefs_key_field;
         }
@@ -459,11 +451,17 @@ class dbPrefs {
                 $this->failQuery();
             }
         } else {
-            $query = sprintf("DELETE FROM %s WHERE %s='%s' AND %s='%s'",
+            $query = sprintf("DELETE FROM %s%s%s WHERE %s%s%s='%s' AND %s%s%s='%s'",
+                             $this->identifier_quote_char,
                              $this->table,
+                             $this->identifier_quote_char,
+                             $this->identifier_quote_char,
                              $this->user_field,
+                             $this->identifier_quote_char,
                              $this->dbh->quoteString($user),
+                             $this->identifier_quote_char,
                              $this->key_field,
+                             $this->identifier_quote_char,
                              $this->dbh->quoteString($key));
 
             $res = $this->dbh->simpleQuery($query);
@@ -552,12 +550,20 @@ class dbPrefs {
                     $this->failQuery();
                 }
             } else {
-                $query = sprintf("REPLACE INTO %s (%s, %s, %s) ".
+                $query = sprintf("REPLACE INTO %s%s%s (%s%s%s, %s%s%s, %s%s%s) ".
                                  "VALUES('%s','%s','%s')",
+                                 $this->identifier_quote_char,
                                  $this->table,
+                                 $this->identifier_quote_char,
+                                 $this->identifier_quote_char,
                                  $this->user_field,
+                                 $this->identifier_quote_char,
+                                 $this->identifier_quote_char,
                                  $this->key_field,
+                                 $this->identifier_quote_char,
+                                 $this->identifier_quote_char,
                                  $this->val_field,
+                                 $this->identifier_quote_char,
                                  $this->dbh->quoteString($user),
                                  $this->dbh->quoteString($key),
                                  $this->dbh->quoteString($value));
@@ -615,22 +621,36 @@ class dbPrefs {
                 }
             } else {
                 $this->dbh->simpleQuery("BEGIN TRANSACTION");
-                $query = sprintf("DELETE FROM %s WHERE %s='%s' AND %s='%s'",
+                $query = sprintf("DELETE FROM %s%s%s WHERE %s%s%s='%s' AND %s%s%s='%s'",
+                                 $this->identifier_quote_char,
                                  $this->table,
+                                 $this->identifier_quote_char,
+                                 $this->identifier_quote_char,
                                  $this->user_field,
+                                 $this->identifier_quote_char,
                                  $this->dbh->quoteString($user),
+                                 $this->identifier_quote_char,
                                  $this->key_field,
+                                 $this->identifier_quote_char,
                                  $this->dbh->quoteString($key));
                 $res = $this->dbh->simpleQuery($query);
                 if (DB::isError($res)) {
                     $this->dbh->simpleQuery("ROLLBACK TRANSACTION");
                     $this->failQuery($res);
                 }
-                $query = sprintf("INSERT INTO %s (%s, %s, %s) VALUES ('%s', '%s', '%s')",
+                $query = sprintf("INSERT INTO %s%s%s (%s%s%s, %s%s%s, %s%s%s) VALUES ('%s', '%s', '%s')",
+                                 $this->identifier_quote_char,
                                  $this->table,
+                                 $this->identifier_quote_char,
+                                 $this->identifier_quote_char,
                                  $this->user_field,
+                                 $this->identifier_quote_char,
+                                 $this->identifier_quote_char,
                                  $this->key_field,
+                                 $this->identifier_quote_char,
+                                 $this->identifier_quote_char,
                                  $this->val_field,
+                                 $this->identifier_quote_char,
                                  $this->dbh->quoteString($user),
                                  $this->dbh->quoteString($key),
                                  $this->dbh->quoteString($value));
@@ -672,21 +692,35 @@ class dbPrefs {
                     $this->failQuery();
                 }
             } else {
-                $query = sprintf("DELETE FROM %s WHERE %s='%s' AND %s='%s'",
+                $query = sprintf("DELETE FROM %s%s%s WHERE %s%s%s='%s' AND %s%s%s='%s'",
+                                 $this->identifier_quote_char,
                                  $this->table,
+                                 $this->identifier_quote_char,
+                                 $this->identifier_quote_char,
                                  $this->user_field,
+                                 $this->identifier_quote_char,
                                  $this->dbh->quoteString($user),
+                                 $this->identifier_quote_char,
                                  $this->key_field,
+                                 $this->identifier_quote_char,
                                  $this->dbh->quoteString($key));
                 $res = $this->dbh->simpleQuery($query);
                 if (DB::isError($res)) {
                     $this->failQuery($res);
                 }
-                $query = sprintf("INSERT INTO %s (%s, %s, %s) VALUES ('%s', '%s', '%s')",
+                $query = sprintf("INSERT INTO %s%s%s (%s%s%s, %s%s%s, %s%s%s) VALUES ('%s', '%s', '%s')",
+                                 $this->identifier_quote_char,
                                  $this->table,
+                                 $this->identifier_quote_char,
+                                 $this->identifier_quote_char,
                                  $this->user_field,
+                                 $this->identifier_quote_char,
+                                 $this->identifier_quote_char,
                                  $this->key_field,
+                                 $this->identifier_quote_char,
+                                 $this->identifier_quote_char,
                                  $this->val_field,
+                                 $this->identifier_quote_char,
                                  $this->dbh->quoteString($user),
                                  $this->dbh->quoteString($key),
                                  $this->dbh->quoteString($value));
@@ -736,12 +770,20 @@ class dbPrefs {
                 $prefs_cache[$row['prefkey']] = $row['prefval'];
             }
         } else {
-            $query = sprintf("SELECT %s as prefkey, %s as prefval FROM %s ".
-                             "WHERE %s = '%s'",
+            $query = sprintf("SELECT %s%s%s as prefkey, %s%s%s as prefval FROM %s%s%s ".
+                             "WHERE %s%s%s = '%s'",
+                             $this->identifier_quote_char,
                              $this->key_field,
+                             $this->identifier_quote_char,
+                             $this->identifier_quote_char,
                              $this->val_field,
+                             $this->identifier_quote_char,
+                             $this->identifier_quote_char,
                              $this->table,
+                             $this->identifier_quote_char,
+                             $this->identifier_quote_char,
                              $this->user_field,
+                             $this->identifier_quote_char,
                              $this->dbh->quoteString($user));
             $res = $this->dbh->query($query);
             if (DB::isError($res)) {
index 64828ff..3b355f9 100755 (executable)
@@ -908,6 +908,11 @@ function sqimap_login ($username, $password, $imap_server_address,
                     $read=sqimap_fgets($imap_stream);
                 }
             }
+            // IMAP server might return some untagged info before
+            // the tagged login command response - skip over that
+            while ($read[0] === '*') {
+                $read = sqimap_fgets($imap_stream);
+            }
             $results=explode(" ",$read,3);
             $response=$results[1];
             $message=$results[2];
@@ -936,7 +941,7 @@ function sqimap_login ($username, $password, $imap_server_address,
          * credentials and use that as the authorization identity.
          */
         $tag=sqimap_session_id(false);
-        $sasl = (isset($sqimap_capabilities['SASL-IR']) && $sqimap_capabilities['SASL-IR']) ? true : false;
+        $sasl = sqimap_capability($imap_stream, 'SASL-IR');
         if(!empty($authz)) {
             $auth = base64_encode("$username\0$authz\0$password");
         } else {
@@ -957,6 +962,11 @@ function sqimap_login ($username, $password, $imap_server_address,
                 $read = sqimap_fgets($imap_stream);
             }
         }
+        // IMAP server might return some untagged info before
+        // the tagged login command response - skip over that
+        while ($read[0] === '*') {
+            $read = sqimap_fgets($imap_stream);
+        }
         $results=explode(" ",$read,3);
         $response=$results[1];
         $message=$results[2];
index 93aaaa8..2b24604 100755 (executable)
@@ -17,7 +17,8 @@
 /**
  * Copy a set of messages ($id) to another mailbox ($mailbox)
  * @param int $imap_stream The resource ID for the IMAP socket
- * @param string $id The list of messages to copy
+ * @param  mixed $id Normally an array which is a list with message UIDs to be copied
+ *                   or a string range such as "1:*" or a simple integer
  * @param string $mailbox The destination to copy to
  * @param bool $handle_errors Show error messages in case of a NO, BAD or BYE response
  * @return bool If the copy completed without errors
@@ -59,14 +60,17 @@ function sqimap_msgs_list_move($imap_stream, $id, $mailbox, $handle_errors = tru
  * Deletes a message and move it to trash or expunge the mailbox
  * @param  resource imap connection
  * @param  string $mailbox mailbox, used for checking if it concerns the trash_folder
- * @param  array $id list with uid's
+ * @param  mixed $id Normally an array which is a list with message UIDs to be deleted
+ *                   or a string range such as "1:*" or a simple integer
  * @param  bool   $bypass_trash (since 1.5.0) skip copy to trash
  * @return array  $aMessageList array with messages containing the new flags and UID @see parseFetch
  * @since 1.4.0
  */
 function sqimap_msgs_list_delete($imap_stream, $mailbox, $id, $bypass_trash=false) {
     // FIXME: Remove globals by introducing an associative array with properties as 4th argument as replacement for the $bypass_trash variable.
-    global $move_to_trash, $trash_folder;
+    global $move_to_trash, $trash_folder, $mark_as_read_upon_delete;
+    if ($mark_as_read_upon_delete)
+        sqimap_toggle_flag($imap_stream, $id, '\\Seen', true, true);
     if (($move_to_trash == true) && ($bypass_trash != true) &&
         (sqimap_mailbox_exists($imap_stream, $trash_folder) &&  ($mailbox != $trash_folder)) ) {
         /**
@@ -83,7 +87,7 @@ function sqimap_msgs_list_delete($imap_stream, $mailbox, $id, $bypass_trash=fals
  * Set a flag on the provided uid list
  * @param  resource imap connection
  * @param  mixed $id Normally an array which is a list with message UIDs to be flagged
- *                   or a string range such as "1:*"
+ *                   or a string range such as "1:*" or a simple integer
  * @param  string $flag Flags to set/unset flags can be i.e.'\Seen', '\Answered', '\Seen \Answered'
  * @param  bool   $set  add (true) or remove (false) the provided flag
  * @param  bool   $handle_errors Show error messages in case of a NO, BAD or BYE response
@@ -93,11 +97,15 @@ function sqimap_toggle_flag($imap_stream, $id, $flag, $set, $handle_errors) {
     $msgs_id = sqimap_message_list_squisher($id);
     $set_string = ($set ? '+' : '-');
 
+    /*
+    * We need to return the data in the same order as the caller supplied
+    * in $id, but IMAP servers are free to return responses in
+    * whatever order they wish... So we need to re-sort manually
+    */
     $aMessageList = array();
-    // TODO: There doesn't seem to be a reason to set up $aMessageList anyway because an empty array for each message doesn't add anything to the parseFetch() return value, so this code block could be simply deleted:
-    if (!is_string($id)) {
-        for ($i=0; $i<sizeof($id); $i++) {
-            $aMessageList["$id[$i]"] = array();
+    if (is_array($id)) {
+        for ($i=0; $i<count($id); $i++) {
+            $aMessageList[$id[$i]] = array();
         }
     }
 
@@ -607,7 +615,7 @@ function sqimap_get_small_header_list($imap_stream, $msg_list,
         */
         if ($bUidFetch) {
             for ($i = 0; $i < sizeof($msg_list); $i++) {
-                $aMessageList["$msg_list[$i]"] = array();
+                $aMessageList[$msg_list[$i]] = array();
             }
         }
     } else {
@@ -638,8 +646,10 @@ function sqimap_get_small_header_list($imap_stream, $msg_list,
 /**
  * Parses a fetch response, currently it can hande FLAGS, HEADERS, RFC822.SIZE, INTERNALDATE and UID
  * @param array    $aResponse Imap response
- * @param array    $aMessageList Placeholder array for results. The keys of the
- *                 placeholder array should be the UID so we can reconstruct the order.
+ * @param array    $aMessageList Placeholder array for results. The keys of this
+ *                               placeholder array should be the UID so we can
+ *                               reconstruct the order (OPTIONAL; this array will
+ *                               be built for the return value fresh if not given)
  * @return array   $aMessageList associative array with messages. Key is the UID, value is an associative array
  * @author Marc Groot Koerkamp
  */
@@ -794,6 +804,7 @@ function parseFetch(&$aResponse,$aMessageList = array()) {
             $msgi = "$unique_id";
             $aMsg['UID'] = $unique_id;
        } else {
+//FIXME: under what circumstances does this happen? We can't use an empty string as an array index in the line just below, so we need to use something else here
             $msgi = '';
        }
        $aMessageList[$msgi] = $aMsg;
index 7e67f00..1f02367 100644 (file)
@@ -396,18 +396,38 @@ function formatBody($imap_stream, $message, $color, $wrap_at, $ent_num, $id, $ma
          */
 
         if ($body_message->header->type1 == 'html') {
-            if ($show_html_default <> 1) {
+            // Do we need to make an HTML part viewable as non-HTML plain text?
+            if ($show_html_default != 1) {
                 $entity_conv = array('&nbsp;' => ' ',
-                                     '<p>'    => "\n",
-                                     '<P>'    => "\n",
-                                     '<br>'   => "\n",
-                                     '<BR>'   => "\n",
-                                     '<br />' => "\n",
-                                     '<BR />' => "\n",
+                                     // These are better done by regex (below)
+                                     // '<p>'    => "\n",
+                                     // '<P>'    => "\n",
+                                     // '<br>'   => "\n",
+                                     // '<BR>'   => "\n",
+                                     // '<br />' => "\n",
+                                     // '<BR />' => "\n",
+                                     // '<tr>'   => "\n",
+                                     // '<div>'  => "\n",
                                      '&gt;'   => '>',
-                                     '&lt;'   => '<');
+                                     '&lt;'   => '<',
+                                     '&amp;'   => '&',
+                                     '&copy;'   => '©');
+                // first, completely remove <style> tags as they aren't useful in this context
+                $body = preg_replace('/<style.*>.*<\/style.*>/isU', '', $body);
+                // emulate how newlines are treated as spaces in HTML
+                $body = preg_replace('/(\r|\n)+/', ' ', $body);
+                // now replace the tags listed just above
                 $body = strtr($body, $entity_conv);
+                // <p>, <br>, <tr> and <div> are best replaced by a newline
+                $body = preg_replace('/<(p|br|tr|div).*>/isU', "\n", $body);
+                // remove the rest of the HTML tags
                 $body = strip_tags($body);
+                // condense multiple spaces into one
+                $body = preg_replace('/[ \t]+/', ' ', $body);
+                // trim each line
+                $body = preg_replace('/ *\n */', "\n", $body);
+                // allow maximum two newlines
+                $body = preg_replace('/\n\n\n+/', "\n\n", $body);
                 $body = trim($body);
                 translateText($body, $wrap_at,
                         $body_message->header->getParameter('charset'));
index 25638fa..339035e 100644 (file)
@@ -181,6 +181,13 @@ function displayHtmlHeader( $title = 'SquirrelMail', $xtra = '', $do_hook = TRUE
         if (!empty($output)) trigger_error('A plugin on the "generic_header" hook has attempted to output directly to the browser', E_USER_ERROR);
     }
 
+    // Add message subject to page title (should only have an effect when loaded in its own browser window/tab)
+    // TODO: For search page, could add " - Search: $what" or something like that
+    global $message;
+    if (!empty($message) && !empty($message->rfc822_header) && !empty($message->rfc822_header->subject))
+        // decodeHeader() should already encode the output, so no sm_encode_html_special_chars()
+        $title .= ' - ' . decodeHeader($message->rfc822_header->subject);
+
     $header_tags .= $xtra;
     $oTemplate->assign('page_title', $title);
 
diff --git a/images/fsf.png b/images/fsf.png
new file mode 100644 (file)
index 0000000..8d11491
Binary files /dev/null and b/images/fsf.png differ
index 6161284..38ba78d 100644 (file)
@@ -78,6 +78,9 @@ $move_to_trash =
 $save_as_draft =
     getPref($data_dir, $username, 'save_as_draft', $default_save_as_draft);
 
+$mark_as_read_upon_delete =
+    getPref($data_dir, $username, 'mark_as_read_upon_delete', FALSE);
+
 if ($default_unseen_type == '') {
     $default_unseen_type = 1;
 }
index 7007ec5..5ae83ad 100644 (file)
@@ -105,6 +105,14 @@ function load_optpage_data_folder() {
     );
 
     $optvals[SMOPT_GRP_SPCFOLDER][] = array(
+        'name'    => 'mark_as_read_upon_delete',
+        'caption' => _("Mark Deleted Messages as Read"),
+        'type'    => SMOPT_TYPE_BOOLEAN,
+        'refresh' => SMOPT_REFRESH_NONE
+    );
+
+//TODO: Arguably, this should go in Compose preferences, not here
+    $optvals[SMOPT_GRP_SPCFOLDER][] = array(
         'name'    => 'save_reply_with_orig',
         'caption' => _("Save Replies with Original Message"),
         'type'    => SMOPT_TYPE_BOOLEAN,
index a566380..160ae38 100644 (file)
@@ -5,7 +5,7 @@
  *
  * @copyright 1999-2022 The SquirrelMail Project Team
  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
- * @version $Id$
+ * @version $Id: sqspell_config.php 14845 2020-01-07 08:09:34Z pdontthink $
  * @package plugins
  * @subpackage squirrelspell
  */
@@ -58,8 +58,7 @@ sqgetGlobalVar('username', $username, SQ_SESSION);
  *
  * @global array $SQSPELL_APP
  */
-$SQSPELL_APP = array('English' => 'ispell -a',
-                     'Spanish' => 'ispell -d spanish -a');
+$SQSPELL_APP = array('English' => 'aspell -a');
 
 /**
  * Sample configuration for PHP pspell extension. Sets dictionary options.
index aeff2e7..9e8bb97 100644 (file)
@@ -8,7 +8,7 @@
  *
  * @copyright 1999-2022 The SquirrelMail Project Team
  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
- * @version $Id$
+ * @version $Id: read_body.php 14845 2020-01-07 08:09:34Z pdontthink $
  * @package squirrelmail
  */
 
@@ -653,6 +653,8 @@ function formatMenubar($aMailbox, $passed_id, $passed_ent_id, $message,
             $oTemplate->assign('move_delete_form_action', $base_uri.'src/read_body.php');
         $oTemplate->assign('delete_form_extra', addHidden('mailbox', $aMailbox['NAME'])."\n" .
                                                 addHidden('msg[0]', $passed_id)."\n" .
+                                                // only need when $return_to_message_list_after_move is off
+                                                addHidden('passed_id', ($next >= 0 ? $next : $prev))."\n" .
                                                 addHidden('startMessage', $startMessage)."\n" );
         if (!(isset($passed_ent_id) && $passed_ent_id)) {
             $oTemplate->assign('can_be_moved', true);
@@ -941,6 +943,13 @@ if ( sqgetGlobalVar('delete_id', $delete_id, SQ_GET) ) {
 }
 
 /**
+ * or delete button... why is handleMessageListForm (per above) conditional anway?
+ */
+if ( sqgetGlobalVar('delete', $ignore, SQ_POST) ) {
+    $sError = handleMessageListForm($imapConnection,$aMailbox);
+}
+
+/**
  * or move button... why is handleMessageListForm (per above) conditional anway?
  */
 if ( sqgetGlobalVar('moveButton', $ignore, SQ_POST) ) {