/* 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;
}
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
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
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
* 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
*
*/
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;
$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;
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;
}
$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);
$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));
}
} 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));
$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));
$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)) {
$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];
* 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 {
$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];
/**
* 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
* 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)) ) {
/**
* 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
$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();
}
}
*/
if ($bUidFetch) {
for ($i = 0; $i < sizeof($msg_list); $i++) {
- $aMessageList["$msg_list[$i]"] = array();
+ $aMessageList[$msg_list[$i]] = array();
}
}
} else {
/**
* 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
*/
$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;
*/
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(' ' => ' ',
- '<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",
'>' => '>',
- '<' => '<');
+ '<' => '<',
+ '&' => '&',
+ '©' => '©');
+ // 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'));
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);
$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;
}
);
$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,
*
* @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
*/
*
* @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.
*
* @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
*/
$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);
}
/**
+ * 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) ) {