' . "\n";
+ }
}
-/*
- * This function loops through a group of messages in the mailbox
- * and shows them to the user.
+
+function setUserPref($username, $pref, $value) {
+ global $data_dir;
+ setPref($data_dir,$username,$pref,$value);
+}
+
+/**
+ * Selects a mailbox for header retrieval.
+ * Cache control for message headers is embedded.
+ *
+ * @param resource $imapConnection imap socket handle
+ * @param string $mailbox mailbox to select and retrieve message headers from
+ * @param array $aConfig array with system config settings and incoming vars
+ * @param array $aProps mailbox specific properties
+ * @return array $aMailbox mailbox array with all relevant information
+ * @author Marc Groot Koerkamp
*/
-function showMessagesForMailbox($imapConnection, $mailbox, $num_msgs,
- $start_msg, $sort, $color, $show_num,
- $use_cache) {
- global $msgs, $msort,
- $sent_folder, $draft_folder,
- $message_highlight_list,
- $auto_expunge, $thread_sort_messages, $allow_server_sort,
- $data_dir, $username, $server_sort_order;
-
- /* if $start_msg is lower than $num_msgs, we probably deleted all messages
- * in the last page. We need to re-adjust the start_msg
- */
+function sqm_api_mailbox_select($imapConnection,$mailbox,$aConfig,$aProps) {
+ /**
+ * NB: retrieve this from the session before accessing this function
+ * and make sure you write it back at the end of the script after
+ * the aMailbox var is added so that the headers are added to the cache
+ */
+ global $mailbox_cache;
+ /**
+ * In case the properties arrays are empty set the defaults.
+ */
+ // Doesn't appear to be used... safe to remove?
+ $aDefaultMbxPref = array ();
+// MBX_PREF_SORT => 0,
+// MBX_PREF_LIMIT => 15,
+// MBX_PREF_AUTO_EXPUNGE => 0,
+// MBX_PREF_INTERNALDATE => 0
+// );
+ /* array_merge doesn't work with integers as keys */
+// foreach ($aDefaultMbxPref as $key => $value) {
+// if (!isset($aProps[$key])) {
+// $aProps[$key] = $value;
+// }
+// }
+ $aDefaultConfigProps = array(
+// 'allow_thread_sort' => 0,
+ 'allow_server_sort' => sqimap_capability($imapConnection,'SORT'),
+// 'charset' => 'US-ASCII',
+ 'user' => false, /* no pref storage if false */
+ 'setindex' => 0,
+// 'search' => 'ALL',
+ 'max_cache_size' => SQM_MAX_MBX_IN_CACHE
+ );
+
+ $aConfig = array_merge($aDefaultConfigProps,$aConfig);
+ $iSetIndx = $aConfig['setindex'];
+
+ $aMbxResponse = sqimap_mailbox_select($imapConnection, $mailbox);
+
+ if ($mailbox_cache) {
+ if (isset($mailbox_cache[$mailbox])) {
+ $aCachedMailbox = $mailbox_cache[$mailbox];
+ } else {
+ $aCachedMailbox = false;
+ }
+ /* cleanup cache */
+ if (count($mailbox_cache) > $aConfig['max_cache_size'] -1) {
+ $aTime = array();
+ foreach($mailbox_cache as $cachedmailbox => $aVal) {
+ $aTime[$aVal['TIMESTAMP']] = $cachedmailbox;
+ }
+ if (ksort($aTime,SORT_NUMERIC)) {
+ for ($i=0,$iCnt=count($mailbox_cache);$i<($iCnt-$aConfig['max_cache_size']);++$i) {
+ $sOldestMbx = array_shift($aTime);
+ /**
+ * Remove only the UIDSET and MSG_HEADERS from cache because those can
+ * contain large amounts of data.
+ */
+ if (isset($mailbox_cache[$sOldestMbx]['UIDSET'])) {
+ $mailbox_cache[$sOldestMbx]['UIDSET']= false;
+ }
+ if (isset($mailbox_cache[$sOldestMbx]['MSG_HEADERS'])) {
+ $mailbox_cache[$sOldestMbx]['MSG_HEADERS'] = false;
+ }
+ }
+ }
+ }
- if($start_msg > $num_msgs) {
- $start_msg -= $show_num;
- if($start_msg < 1) {
- $start_msg = 1;
- }
- }
-
- /* This code and the next if() block check for
- * server-side sorting methods. The $id array is
- * formatted and $sort is set to 6 to disable
- * SM internal sorting
- */
- if ($thread_sort_messages == 1) {
- $id = get_thread_sort($imapConnection);
- if ($id == 'no') {
- echo '
Thread sorting is not'.
- ' supported by your IMAP server. Please report this'.
- ' to the system administrator.
' .
+ _("Server-side sorting is not supported by your IMAP server.") . ' ' .
+ _("Please contact your system administrator and report this error.") .
+ '
';
+ } else {
+ $aMailbox['UIDSET'][$iSetIndx] = $id;
+ }
+ break;
+ default:
+ $id = NULL;
+ if ($aMailbox['SEARCH'][$iSetIndx] != 'ALL') {
+ $id = sqimap_run_search($imapConnection, $aMailbox['SEARCH'][$iSetIndx], $aMailbox['CHARSET'][$iSetIndx]);
+ }
+ $sSortField = getSortField($aMailbox['SORT'],false);
+ $aMailbox['UIDSET'][$iSetIndx] = get_squirrel_sort($imapConnection, $sSortField, $bDirection, $id);
+ break;
+ }
+ return $error;
+}
+
+
+
+
+function fetchMessageHeaders($imapConnection, &$aMailbox) {
+
+ /**
+ * Retrieve the UIDSET.
+ * Setindex is used to be able to store multiple uid sets. That will make it
+ * possible to display the mailbox multiple times in different sort order
+ * or to store serach results separate from normal mailbox view.
+ */
+ $iSetIndx = (isset($aMailbox['SETINDEX'])) ? $aMailbox['SETINDEX'] : 0;
+
+ $iLimit = ($aMailbox['SHOWALL'][$iSetIndx]) ? $aMailbox['EXISTS'] : $aMailbox['LIMIT'];
+ /**
+ * Adjust the start_msg
+ */
+ $start_msg = $aMailbox['PAGEOFFSET'];
+ if($aMailbox['PAGEOFFSET'] > $aMailbox['EXISTS']) {
+ $start_msg -= $aMailbox['LIMIT'];
+ if($start_msg < 1) {
+ $start_msg = 1;
+ }
+ }
+
+
+ if (is_array($aMailbox['UIDSET'])) {
+ $aUid =& $aMailbox['UIDSET'][$iSetIndx];
} else {
- $i = 1;
- }
- reset($msort);
- $k = 0;
- do {
- $key = key($msort);
- next($msort);
- $k++;
- } while (isset ($key) && ($k < $i));
- printMessageInfo($imapConnection, $t, $i, $key, $mailbox, $sort,
- $real_startMessage, 0, 0);
- } else {
- $i = $start_msg;
- reset($msort);
- $k = 0;
- do {
- $key = key($msort);
- next($msort);
- $k++;
- } while (isset ($key) && ($k < $i));
- do {
- printMessageInfo($imapConnection, $t, $i, $key, $mailbox,
- $sort, $real_startMessage, 0, 0);
- $key = key($msort);
- $t++;
- $i++;
- next($msort);
- } while ($i && $i < $endVar);
- }
-
- echo ''
- . "
"
- . "
$paginator_str
"
- . "
$msg_cnt_str
"
- . "
";
- /* End of message-list table */
-
- do_hook('mailbox_index_after');
- echo "\n";
+ $aUid = false;
+ }
+
+ // initialize the fields we want to retrieve:
+ $aHeaderFields = array('Date', 'To', 'Cc', 'From', 'Subject', 'X-Priority', 'Content-Type');
+ $aFetchItems = array('FLAGS', 'RFC822.SIZE');
+
+ // Are we sorting on internaldate then retrieve the internaldate value as well
+ if ($aMailbox['INTERNALDATE']) {
+ $aFetchItems[] = 'INTERNALDATE';
+ }
+
+
+ /**
+ * A uidset with sorted uid's is available. We can use the cache
+ */
+ if (($aMailbox['SORT'] != SQSORT_NONE || $aMailbox['SEARCH'][$iSetIndx] != 'ALL') &&
+ isset($aUid) && $aUid ) {
+
+ // limit the cache to SQM_MAX_PAGES_IN_CACHE
+ if (!$aMailbox['SHOWALL'][$iSetIndx]) {
+ $iMaxMsgs = $iLimit * SQM_MAX_PAGES_IN_CACHE;
+ $iCacheSize = count($aMailbox['MSG_HEADERS']);
+ if ($iCacheSize > $iMaxMsgs) {
+ $iReduce = $iCacheSize - $iMaxMsgs;
+ foreach ($aMailbox['MSG_HEADERS'] as $iUid => $value) {
+ if ($iReduce) {
+ unset($aMailbox['MSG_HEADERS'][$iUid]);
+ } else {
+ break;
+ }
+ --$iReduce;
+ }
+ }
+ }
+
+ $id_slice = array_slice($aUid,$start_msg-1,$iLimit);
+ /* do some funky cache checks */
+ $aUidCached = array_keys($aMailbox['MSG_HEADERS']);
+ $aUidNotCached = array_values(array_diff($id_slice,$aUidCached));
+ /**
+ * $aUidNotCached contains an array with UID's which need to be fetched to
+ * complete the needed message headers.
+ */
+ if (count($aUidNotCached)) {
+ $aMsgs = sqimap_get_small_header_list($imapConnection,$aUidNotCached,
+ $aHeaderFields,$aFetchItems);
+ // append the msgs to the existend headers
+ $aMailbox['MSG_HEADERS'] += $aMsgs;
+ }
+
+ } else {
+ /**
+ * Initialize the sorted UID list and fetch the visible message headers
+ */
+ if ($aMailbox['SORT'] != SQSORT_NONE || $aMailbox['SEARCH'][$iSetIndx] != 'ALL') {// || $aMailbox['SORT_METHOD'] & SQSORT_THREAD 'THREAD') {
+
+ $error = false;
+ if ($aMailbox['SEARCH'][$iSetIndx] && $aMailbox['SORT'] == 0) {
+ $aUid = sqimap_run_search($imapConnection, $aMailbox['SEARCH'][$iSetIndx], $aMailbox['CHARSET'][$iSetIndx]);
+ } else {
+ $error = get_sorted_msgs_list($imapConnection,$aMailbox,$error);
+ $aUid = $aMailbox['UIDSET'][$iSetIndx];
+ }
+ if ($error === false) {
+ $id_slice = array_slice($aUid,$aMailbox['OFFSET'], $iLimit);
+ if (count($id_slice)) {
+ $aMailbox['MSG_HEADERS'] = sqimap_get_small_header_list($imapConnection,$id_slice,
+ $aHeaderFields,$aFetchItems);
+ } else {
+ return false;
+ }
+
+ } else {
+ // FIX ME, format message and fallback to squirrel sort
+ if ($error) {
+ echo $error;
+ }
+ }
+ } else {
+ // limit the cache to SQM_MAX_PAGES_IN_CACHE
+ if (!$aMailbox['SHOWALL'][$iSetIndx] && isset($aMailbox['MSG_HEADERS']) && is_array($aMailbox['MSG_HEADERS'])) {
+ $iMaxMsgs = $iLimit * SQM_MAX_PAGES_IN_CACHE;
+ $iCacheSize = count($aMailbox['MSG_HEADERS']);
+ if ($iCacheSize > $iMaxMsgs) {
+ $iReduce = $iCacheSize - $iMaxMsgs;
+ foreach ($aMailbox['MSG_HEADERS'] as $iUid => $value) {
+ if ($iReduce) {
+ $iId = $aMailbox['MSG_HEADERS'][$iUid]['ID'];
+ unset($aMailbox['MSG_HEADERS'][$iUid]);
+ unset($aMailbox['ID'][$iId]);
+ } else {
+ break;
+ }
+ --$iReduce;
+ }
+ }
+ }
+
+ /**
+ * retrieve messages by sequence id's and fetch the UID to retrieve
+ * the UID. for sorted lists this is not needed because a UID FETCH
+ * automaticly add the UID value in fetch results
+ **/
+ $aFetchItems[] = 'UID';
+
+ //create id range
+ $iRangeStart = $aMailbox['EXISTS'] - $aMailbox['OFFSET'];
+ $iRangeEnd = ($iRangeStart > $iLimit) ?
+ ($iRangeStart - $iLimit+1):1;
+
+ $id_slice = range($iRangeStart, $iRangeEnd);
+ /**
+ * Non sorted mailbox with cached message headers
+ */
+ if (isset($aMailbox['ID']) && is_array($aMailbox['ID'])) {
+ // the fetched id => uid relation
+ $aId = $aMailbox['ID'];
+ $aIdCached = array();
+ foreach ($aId as $iId => $iUid) {
+ if (isset($aMailbox['MSG_HEADERS'][$iUid])) {
+ if ($iId <= $iRangeStart && $iId >= $iRangeEnd) {
+ $aIdCached[] = $iId;
+ }
+ }
+ }
+ $aIdNotCached = array_diff($id_slice,$aIdCached);
+ } else {
+ $aIdNotCached = $id_slice;
+ }
+
+ if (count($aIdNotCached)) {
+ $aMsgs = sqimap_get_small_header_list($imapConnection,$aIdNotCached,
+ $aHeaderFields,$aFetchItems);
+ // append the msgs to the existend headers
+ if (isset($aMailbox['MSG_HEADERS']) && is_array($aMailbox['MSG_HEADERS'])) {
+ $aMailbox['MSG_HEADERS'] += $aMsgs;
+ } else {
+ $aMailbox['MSG_HEADERS'] = $aMsgs;
+ }
+ // update the ID array
+ foreach ($aMsgs as $iUid => $aMsg) {
+ if (isset($aMsg['ID'])) {
+ $aMailbox['ID'][$aMsg['ID']] = $iUid;
+ }
+ }
+ }
+
+ /**
+ * In unsorted state we show newest messages first which means
+ * that the UIDSET which represents the order of the messages
+ * should contain a high to low ordered UID list
+ */
+ $aSortedUidList = array();
+ foreach ($id_slice as $iId) {
+ if (isset($aMailbox['ID'][$iId])) {
+ $aSortedUidList[] = $aMailbox['ID'][$iId];
+ }
+ }
+ $aMailbox['UIDSET'][$iSetIndx] = $aSortedUidList;
+ $aMailbox['OFFSET'] = 0;
+ }
+ }
+ return true;
}
-/*
- * Displays the standard message list header. To finish the table,
- * you need to do a "";
+/**
+ * This function loops through a group of messages in the mailbox
+ * and shows them to the user.
*
- * $moveURL is the URL to submit the delete/move form to
- * $mailbox is the current mailbox
- * $sort is the current sorting method (-1 for no sorting available [searches])
- * $Message is a message that is centered on top of the list
- * $More is a second line that is left aligned
+ * @param mixed $imapConnection
+ * @param array $aMailbox associative array with mailbox related vars
*/
-
-function mail_message_listing_beginning ($imapConnection, $moveURL,
- $mailbox = '', $sort = -1,
- $msg_cnt_str = '',
- $paginator = ' ',
- $start_msg = 1) {
- global $color, $index_order, $auto_expunge, $move_to_trash, $base_uri,
- $checkall, $sent_folder, $draft_folder, $thread_sort_messages,
- $allow_thread_sort, $allow_server_sort, $server_sort_order,
- $lastTargetMailbox;
-
- $urlMailbox = urlencode($mailbox);
-
- /*
- * This is the beginning of the message list table.
- * It wraps around all messages
- */
- echo "