/** * 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 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. */ $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_server_sort' => sqimap_capability($imapConnection, 'SORT'), 'user' => false, 'setindex' => 0, '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; } } } } } else { $aCachedMailbox = false; } /** * Deal with imap servers that do not return the required UIDNEXT or * UIDVALIDITY response * from a SELECT call (since rfc 3501 it's required). */ if (!isset($aMbxResponse['UIDNEXT']) || !isset($aMbxResponse['UIDVALIDITY'])) { $aStatus = sqimap_status_messages($imapConnection, $mailbox, array('UIDNEXT', 'UIDVALIDITY')); $aMbxResponse['UIDNEXT'] = $aStatus['UIDNEXT']; $aMbxResponse['UIDVALIDTY'] = $aStatus['UIDVALIDITY']; } $aMailbox['UIDSET'][$iSetIndx] = false; $aMailbox['ID'] = false; $aMailbox['SETINDEX'] = $iSetIndx; if ($aCachedMailbox) { /** * Validate integrity of cached data */ if ($aCachedMailbox['EXISTS'] == $aMbxResponse['EXISTS'] && $aMbxResponse['EXISTS'] && $aCachedMailbox['UIDVALIDITY'] == $aMbxResponse['UIDVALIDITY'] && $aCachedMailbox['UIDNEXT'] == $aMbxResponse['UIDNEXT'] && isset($aCachedMailbox['SEARCH'][$iSetIndx]) && (!isset($aConfig['search']) || $aCachedMailbox['SEARCH'][$iSetIndx] == $aConfig['search'])) { if (isset($aCachedMailbox['MSG_HEADERS'])) { $aMailbox['MSG_HEADERS'] = $aCachedMailbox['MSG_HEADERS']; } $aMailbox['ID'] = $aCachedMailbox['ID']; if (isset($aCachedMailbox['UIDSET'][$iSetIndx]) && $aCachedMailbox['UIDSET'][$iSetIndx]) { if (isset($aProps[MBX_PREF_SORT]) && $aProps[MBX_PREF_SORT] != $aCachedMailbox['SORT']) { $newsort = $aProps[MBX_PREF_SORT]; $oldsort = $aCachedMailbox['SORT']; /** * If it concerns a reverse sort we do not need to invalidate * the cached sorted UIDSET, a reverse is sufficient. */ if ($newsort % 2 && $newsort + 1 == $oldsort || !($newsort % 2) && $newsort - 1 == $oldsort) { $aMailbox['UIDSET'][$iSetIndx] = array_reverse($aCachedMailbox['UIDSET'][$iSetIndx]); } else { $server_sort_array = false; $aMailbox['MSG_HEADERS'] = false; $aMailbox['ID'] = false; } // store the new sort value in the mailbox pref if ($aConfig['user']) { // FIXME, in ideal situation, we write back the // prefs at the end of the script setUserPref($aConfig['user'], "pref_{$mailbox}", serialize($aProps)); } } else { $aMailbox['UIDSET'][$iSetIndx] = $aCachedMailbox['UIDSET'][$iSetIndx]; } } } } /** * Restore the offset in the paginator if no new offset is provided. */ if (isset($aMailbox['UIDSET'][$iSetIndx]) && !isset($aConfig['offset']) && $aCachedMailbox['OFFSET']) { $aMailbox['OFFSET'] = $aCachedMailbox['OFFSET']; $aMailbox['PAGEOFFSET'] = $aCachedMailbox['PAGEOFFSET']; } else { $aMailbox['OFFSET'] = isset($aConfig['offset']) && $aConfig['offset'] ? $aConfig['offset'] - 1 : 0; $aMailbox['PAGEOFFSET'] = isset($aConfig['offset']) && $aConfig['offset'] ? $aConfig['offset'] : 1; } /** * Restore the showall value no new showall value is provided. */ if (isset($aMailbox['UIDSET'][$iSetIndx]) && !isset($aConfig['showall']) && isset($aCachedMailbox['SHOWALL'][$iSetIndx]) && $aCachedMailbox['SHOWALL'][$iSetIndx]) { $aMailbox['SHOWALL'][$iSetIndx] = $aCachedMailbox['SHOWALL'][$iSetIndx]; } else { $aMailbox['SHOWALL'][$iSetIndx] = isset($aConfig['showall']) && $aConfig['showall'] ? 1 : 0; } if (!isset($aProps[MBX_PREF_SORT]) && isset($aCachedMailbox['SORT'])) { $aMailbox['SORT'] = $aCachedMailbox['SORT']; } else { $aMailbox['SORT'] = isset($aProps[MBX_PREF_SORT]) ? $aProps[MBX_PREF_SORT] : 0; } if (!isset($aProps[MBX_PREF_LIMIT]) && isset($aCachedMailbox['LIMIT'])) { $aMailbox['LIMIT'] = $aCachedMailbox['LIMIT']; } else { $aMailbox['LIMIT'] = isset($aProps[MBX_PREF_LIMIT]) ? $aProps[MBX_PREF_LIMIT] : 15; } if (!isset($aProps[MBX_PREF_INTERNALDATE]) && isset($aCachedMailbox['INTERNALDATE'])) { $aMailbox['INTERNALDATE'] = $aCachedMailbox['INTERNALDATE']; } else { $aMailbox['INTERNALDATE'] = isset($aProps[MBX_PREF_INTERNALDATE]) ? $aProps[MBX_PREF_INTERNALDATE] : false; } if (!isset($aProps[MBX_PREF_AUTO_EXPUNGE]) && isset($aCachedMailbox['AUTO_EXPUNGE'])) { $aMailbox['AUTO_EXPUNGE'] = $aCachedMailbox['AUTO_EXPUNGE']; } else { $aMailbox['AUTO_EXPUNGE'] = isset($aProps[MBX_PREF_AUTO_EXPUNGE]) ? $aProps[MBX_PREF_AUTO_EXPUNGE] : false; } if (!isset($aConfig['allow_thread_sort']) && isset($aCachedMailbox['ALLOW_THREAD'])) { $aMailbox['ALLOW_THREAD'] = $aCachedMailbox['ALLOW_THREAD']; } else { $aMailbox['ALLOW_THREAD'] = isset($aConfig['allow_thread_sort']) ? $aConfig['allow_thread_sort'] : false; } if (!isset($aConfig['search']) && isset($aCachedMailbox['SEARCH'][$iSetIndx])) { $aMailbox['SEARCH'][$iSetIndx] = $aCachedMailbox['SEARCH'][$iSetIndx]; } else { $aMailbox['SEARCH'][$iSetIndx] = isset($aConfig['search']) ? $aConfig['search'] : 'ALL'; } if (!isset($aConfig['charset']) && isset($aCachedMailbox['CHARSET'][$iSetIndx])) { $aMailbox['CHARSET'][$iSetIndx] = $aCachedMailbox['CHARSET'][$iSetIndx]; } else { $aMailbox['CHARSET'][$iSetIndx] = isset($aConfig['charset']) ? $aConfig['charset'] : 'US-ASCII'; } $aMailbox['NAME'] = $mailbox; $aMailbox['EXISTS'] = $aMbxResponse['EXISTS']; $aMailbox['SEEN'] = isset($aMbxResponse['SEEN']) ? $aMbxResponse['SEEN'] : $aMbxResponse['EXISTS']; $aMailbox['RECENT'] = isset($aMbxResponse['RECENT']) ? $aMbxResponse['RECENT'] : 0; $aMailbox['UIDVALIDITY'] = $aMbxResponse['UIDVALIDITY']; $aMailbox['UIDNEXT'] = $aMbxResponse['UIDNEXT']; $aMailbox['PERMANENTFLAGS'] = $aMbxResponse['PERMANENTFLAGS']; $aMailbox['RIGHTS'] = $aMbxResponse['RIGHTS']; /* decide if we are thread sorting or not */ if (!$aMailbox['ALLOW_THREAD']) { if ($aMailbox['SORT'] & SQSORT_THREAD) { $aMailbox['SORT'] -= SQSORT_THREAD; } } if ($aMailbox['SORT'] & SQSORT_THREAD) { $aMailbox['SORT_METHOD'] = 'THREAD'; $aMailbox['THREAD_INDENT'] = $aCachedMailbox['THREAD_INDENT']; } else { if (isset($aConfig['allow_server_sort']) && $aConfig['allow_server_sort']) { $aMailbox['SORT_METHOD'] = 'SERVER'; $aMailbox['THREAD_INDENT'] = false; } else { $aMailbox['SORT_METHOD'] = 'SQUIRREL'; $aMailbox['THREAD_INDENT'] = false; } } /* set a timestamp for cachecontrol */ $aMailbox['TIMESTAMP'] = time(); return $aMailbox; }
function sqimap_get_delimiter($imap_stream = false) { global $sqimap_delimiter, $optional_delimiter; /* Use configured delimiter if set */ if (!empty($optional_delimiter) && $optional_delimiter != 'detect') { return $optional_delimiter; } /* Do some caching here */ if (!$sqimap_delimiter) { if (sqimap_capability($imap_stream, 'NAMESPACE')) { /* * According to something that I can't find, this is supposed to work on all systems * OS: This won't work in Courier IMAP. * OS: According to rfc2342 response from NAMESPACE command is: * OS: * NAMESPACE (PERSONAL NAMESPACES) (OTHER_USERS NAMESPACE) (SHARED NAMESPACES) * OS: We want to lookup all personal NAMESPACES... */ $read = sqimap_run_command($imap_stream, 'NAMESPACE', true, $a, $b); if (eregi('\\* NAMESPACE +(\\( *\\(.+\\) *\\)|NIL) +(\\( *\\(.+\\) *\\)|NIL) +(\\( *\\(.+\\) *\\)|NIL)', $read[0], $data)) { if (eregi('^\\( *\\((.*)\\) *\\)', $data[1], $data2)) { $pn = $data2[1]; } $pna = explode(')(', $pn); while (list($k, $v) = each($pna)) { $lst = explode('"', $v); if (isset($lst[3])) { $pn[$lst[1]] = $lst[3]; } else { $pn[$lst[1]] = ''; } } } $sqimap_delimiter = $pn[0]; } else { fputs($imap_stream, ". LIST \"INBOX\" \"\"\r\n"); $read = sqimap_read_data($imap_stream, '.', true, $a, $b); $quote_position = strpos($read[0], '"'); $sqimap_delimiter = substr($read[0], $quote_position + 1, 1); } } return $sqimap_delimiter; }
/** * This function loops through a group of messages in the mailbox * and shows them to the user. * * @param resource $imapConnection * @param array $aMailbox associative array with mailbox related vars * @param array $aProps * @param int $iError error code, 0 is no error */ function showMessagesForMailbox($imapConnection, &$aMailbox, $aProps, &$iError) { global $PHP_SELF; global $boxes, $show_copy_buttons; $highlight_list = isset($aProps['config']['highlight_list']) ? $aProps['config']['highlight_list'] : false; $fancy_index_highlite = isset($aProps['config']['fancy_index_highlite']) ? $aProps['config']['fancy_index_highlite'] : true; $aColumnsDesc = isset($aProps['columns']) ? $aProps['columns'] : false; $iAccount = isset($aProps['account']) ? (int) $aProps['account'] : 0; $sMailbox = isset($aProps['mailbox']) ? $aProps['mailbox'] : false; $sTargetModule = isset($aProps['module']) ? $aProps['module'] : 'read_body'; $show_flag_buttons = isset($aProps['config']['show_flag_buttons']) ? $aProps['config']['show_flag_buttons'] : true; /* allows to control copy button in function call. If array key is not set, code follows user preferences */ if (isset($aProps['config']['show_copy_buttons'])) { $show_copy_buttons = $aProps['config']['show_copy_buttons']; } $lastTargetMailbox = isset($aProps['config']['lastTargetMailbox']) ? $aProps['config']['lastTargetMailbox'] : ''; $aOrder = array_keys($aProps['columns']); $trash_folder = isset($aProps['config']['trash_folder']) && $aProps['config']['trash_folder'] ? $aProps['config']['trash_folder'] : false; $sent_folder = isset($aProps['config']['sent_folder']) && $aProps['config']['sent_folder'] ? $aProps['config']['sent_folder'] : false; $draft_folder = isset($aProps['config']['draft_folder']) && $aProps['config']['draft_folder'] ? $aProps['config']['draft_folder'] : false; $page_selector = isset($aProps['config']['page_selector']) ? $aProps['config']['page_selector'] : false; $page_selector_max = isset($aProps['config']['page_selector_max']) ? $aProps['config']['page_selector_max'] : 10; $color = $aProps['config']['color']; /* * Form ID */ static $iFormId; if (!isset($iFormId)) { $iFormId = 1; } else { ++$iFormId; } // store the columns to fetch so we can pick them up in read_body // where we validate the cache. calcFetchColumns($aMailbox, $aProps); $iError = fetchMessageHeaders($imapConnection, $aMailbox); if ($iError) { return array(); } else { $aMessages = prepareMessageList($aMailbox, $aProps); } $iSetIndx = $aMailbox['SETINDEX']; $iLimit = $aMailbox['SHOWALL'][$iSetIndx] ? $aMailbox['EXISTS'] : $aMailbox['LIMIT']; $iEnd = $aMailbox['PAGEOFFSET'] + ($iLimit - 1) < $aMailbox['EXISTS'] ? $aMailbox['PAGEOFFSET'] + $iLimit - 1 : $aMailbox['EXISTS']; $iNumberOfMessages = $aMailbox['TOTAL'][$iSetIndx]; $iEnd = min($iEnd, $iNumberOfMessages); $php_self = $PHP_SELF; $urlMailbox = urlencode($aMailbox['NAME']); if (preg_match('/^(.+)\\?.+$/', $php_self, $regs)) { $source_url = $regs[1]; } else { $source_url = $php_self; } $baseurl = $source_url . '?mailbox=' . urlencode($aMailbox['NAME']) . '&account=' . $aMailbox['ACCOUNT'] . (strpos($source_url, 'src/search.php') ? '&smtoken=' . sm_generate_security_token() : ''); $where = urlencode($aMailbox['SEARCH'][$iSetIndx][0]); $what = urlencode($aMailbox['SEARCH'][$iSetIndx][1]); $baseurl .= '&where=' . $where . '&what=' . $what; /* build thread sorting links */ $newsort = $aMailbox['SORT']; if (sqimap_capability($imapConnection, 'THREAD')) { if ($aMailbox['SORT'] & SQSORT_THREAD) { $newsort -= SQSORT_THREAD; $thread_name = _("Unthread View"); } else { $thread_name = _("Thread View"); $newsort = $aMailbox['SORT'] + SQSORT_THREAD; } $thread_link_uri = $baseurl . '&srt=' . $newsort . '&startMessage=1'; } else { $thread_link_uri = ''; $thread_name = ''; } $sort = $aMailbox['SORT']; /* FIX ME ADD CHECKBOX CONTROL. No checkbox => no buttons */ /* future admin control over displayable buttons */ $aAdminControl = array('markFlagged' => 1, 'markUnflagged' => 1, 'markRead' => 1, 'markUnread' => 1, 'forward' => 1, 'delete' => 1, 'undeleteButton' => 1, 'bypass_trash' => 1, 'expungeButton' => 1, 'moveButton' => 1, 'copyButton' => 1); /* user prefs control */ $aUserControl = array('markFlagged' => $show_flag_buttons, 'markUnflagged' => $show_flag_buttons, 'markRead' => 1, 'markUnread' => 1, 'forward' => 1, 'delete' => 1, 'undeleteButton' => 1, 'bypass_trash' => 1, 'expungeButton' => 1, 'moveButton' => 1, 'copyButton' => $show_copy_buttons); $showDelete = $aMailbox['RIGHTS'] != 'READ-ONLY' && in_array('\\deleted', $aMailbox['PERMANENTFLAGS'], true) ? true : false; $showByPassTrash = $aMailbox['AUTO_EXPUNGE'] && $aMailbox['RIGHTS'] != 'READ-ONLY' && in_array('\\deleted', $aMailbox['PERMANENTFLAGS'], true) && $trash_folder ? true : false; // $showUndelete = !$aMailbox['AUTO_EXPUNGE'] && $aMailbox['RIGHTS'] != 'READ-ONLY' && in_array('\\deleted', $aMailbox['PERMANENTFLAGS'], true) ? true : false; $showMove = $aMailbox['RIGHTS'] != 'READ-ONLY' ? true : false; $showExpunge = !$aMailbox['AUTO_EXPUNGE'] && $aMailbox['RIGHTS'] != 'READ-ONLY' && in_array('\\deleted', $aMailbox['PERMANENTFLAGS'], true) ? true : false; /* Button options that depend on IMAP server and selected folder */ $aImapControl = array('markUnflagged' => in_array('\\flagged', $aMailbox['PERMANENTFLAGS'], true), 'markFlagged' => in_array('\\flagged', $aMailbox['PERMANENTFLAGS'], true), 'markRead' => in_array('\\seen', $aMailbox['PERMANENTFLAGS'], true), 'markUnread' => in_array('\\seen', $aMailbox['PERMANENTFLAGS'], true), 'forward' => 1, 'delete' => $showDelete, 'undeleteButton' => $showUndelete, 'bypass_trash' => $showByPassTrash, 'expungeButton' => $showExpunge, 'moveButton' => $showMove, 'copyButton' => 1); /* Button strings */ $aButtonStrings = array('markFlagged' => _("Flag"), 'markUnflagged' => _("Unflag"), 'markRead' => _("Read"), 'markUnread' => _("Unread"), 'forward' => _("Forward"), 'delete' => _("Delete"), 'undeleteButton' => _("Undelete"), 'bypass_trash' => _("Bypass Trash"), 'expungeButton' => _("Expunge"), 'moveButton' => _("Move"), 'copyButton' => _("Copy")); /* Button access keys */ global $accesskey_mailbox_flag, $accesskey_mailbox_unflag, $accesskey_mailbox_read, $accesskey_mailbox_unread, $accesskey_mailbox_forward, $accesskey_mailbox_delete, $accesskey_mailbox_undelete, $accesskey_mailbox_bypass_trash, $accesskey_mailbox_expunge, $accesskey_mailbox_move, $accesskey_mailbox_copy, $accesskey_mailbox_move_to; $aButtonAccessKeys = array('markFlagged' => $accesskey_mailbox_flag, 'markUnflagged' => $accesskey_mailbox_unflag, 'markRead' => $accesskey_mailbox_read, 'markUnread' => $accesskey_mailbox_unread, 'forward' => $accesskey_mailbox_forward, 'delete' => $accesskey_mailbox_delete, 'undeleteButton' => $accesskey_mailbox_undelete, 'bypass_trash' => $accesskey_mailbox_bypass_trash, 'expungeButton' => $accesskey_mailbox_expunge, 'moveButton' => $accesskey_mailbox_move, 'copyButton' => $accesskey_mailbox_copy); /** * Register buttons in order to an array * The key is the "name", the first element of the value array is the "value", second argument is the type. */ $aFormElements = array(); foreach ($aAdminControl as $k => $v) { if ($v & $aUserControl[$k] & $aImapControl[$k]) { switch ($k) { case 'markFlagged': case 'markUnflagged': case 'markRead': case 'markUnread': case 'delete': case 'undeleteButton': case 'expungeButton': case 'forward': $aFormElements[$k] = array('value' => $aButtonStrings[$k], 'type' => 'submit', 'accesskey' => isset($aButtonAccessKeys[$k]) ? $aButtonAccessKeys[$k] : 'NONE'); break; case 'bypass_trash': $aFormElements[$k] = array('value' => $aButtonStrings[$k], 'type' => 'checkbox', 'accesskey' => isset($aButtonAccessKeys[$k]) ? $aButtonAccessKeys[$k] : 'NONE'); break; case 'moveButton': case 'copyButton': $aFormElements['targetMailbox'] = array('options_list' => sqimap_mailbox_option_list($imapConnection, array(strtolower($lastTargetMailbox)), 0, $boxes), 'type' => 'select', 'accesskey' => $accesskey_mailbox_move_to); $aFormElements['mailbox'] = array('value' => $aMailbox['NAME'], 'type' => 'hidden'); $aFormElements['startMessage'] = array('value' => $aMailbox['PAGEOFFSET'], 'type' => 'hidden'); $aFormElements[$k] = array('value' => $aButtonStrings[$k], 'type' => 'submit', 'accesskey' => isset($aButtonAccessKeys[$k]) ? $aButtonAccessKeys[$k] : 'NONE'); break; } } $aFormElements['account'] = array('value' => $iAccount, 'type' => 'hidden'); } do_hook('message_list_controls', $aFormElements); /* * This is the beginning of the message list table. * It wraps around all messages */ $safe_name = preg_replace("/[^0-9A-Za-z_]/", '_', $aMailbox['NAME']); $form_name = "FormMsgs" . $safe_name; //if (!sqgetGlobalVar('align',$align,SQ_SESSION)) { $align = array('left' => 'left', 'right' => 'right'); //} //sm_print_r($align); /* finally set the template vars */ // FIXME, before we support multiple templates we must review the names of the vars // BUMP! $aTemplate['color'] = $color; $aTemplate['form_name'] = "FormMsgs" . $safe_name; $aTemplate['form_id'] = 'mbx_' . $iFormId; $aTemplate['page_selector'] = $page_selector; $aTemplate['page_selector_max'] = $page_selector_max; $aTemplate['messagesPerPage'] = $aMailbox['LIMIT']; $aTemplate['showall'] = $aMailbox['SHOWALL'][$iSetIndx]; $aTemplate['end_msg'] = $iEnd; $aTemplate['align'] = $align; $aTemplate['iNumberOfMessages'] = $iNumberOfMessages; $aTemplate['aOrder'] = $aOrder; $aTemplate['aFormElements'] = $aFormElements; $aTemplate['sort'] = $sort; $aTemplate['pageOffset'] = $aMailbox['PAGEOFFSET']; $aTemplate['baseurl'] = $baseurl; $aTemplate['aMessages'] =& $aMessages; $aTemplate['trash_folder'] = $trash_folder; $aTemplate['sent_folder'] = $sent_folder; $aTemplate['draft_folder'] = $draft_folder; $aTemplate['thread_link_uri'] = $thread_link_uri; $aTemplate['thread_name'] = $thread_name; $aTemplate['php_self'] = str_replace('&', '&', $php_self); $aTemplate['mailbox'] = $sMailbox; //FIXME: javascript_on is always assigned to the template object in places like init.php; is there some reason to reassign it here? is there some chance that it was changed? if not, please remove this line! $aTemplate['javascript_on'] = isset($aProps['config']['javascript_on']) ? $aProps['config']['javascript_on'] : false; $aTemplate['enablesort'] = isset($aProps['config']['enablesort']) ? $aProps['config']['enablesort'] : false; $aTemplate['icon_theme'] = isset($aProps['config']['icon_theme']) ? $aProps['config']['icon_theme'] : false; $aTemplate['use_icons'] = isset($aProps['config']['use_icons']) ? $aProps['config']['use_icons'] : false; $aTemplate['alt_index_colors'] = isset($aProps['config']['alt_index_colors']) ? $aProps['config']['alt_index_colors'] : false; $aTemplate['fancy_index_highlite'] = $fancy_index_highlite; /** * Set up sort possibilities; one could argue that this is best * placed in the template, but most template authors won't understand * or need to understand it, so some advanced templates can override * it if they do something different. */ if (!($aTemplate['sort'] & SQSORT_THREAD) && $aTemplate['enablesort']) { $aTemplate['aSortSupported'] = array(SQM_COL_SUBJ => array(SQSORT_SUBJ_ASC, SQSORT_SUBJ_DESC), SQM_COL_DATE => array(SQSORT_DATE_DESC, SQSORT_DATE_ASC), SQM_COL_INT_DATE => array(SQSORT_INT_DATE_DESC, SQSORT_INT_DATE_ASC), SQM_COL_FROM => array(SQSORT_FROM_ASC, SQSORT_FROM_DESC), SQM_COL_TO => array(SQSORT_TO_ASC, SQSORT_TO_DESC), SQM_COL_CC => array(SQSORT_CC_ASC, SQSORT_CC_DESC), SQM_COL_SIZE => array(SQSORT_SIZE_ASC, SQSORT_SIZE_DESC)); } else { $aTemplate['aSortSupported'] = array(); } /** * Figure out which columns should serve as labels for checkbox: * we try to grab the two columns before and after the checkbox, * except the subject column, since it is the link that opens * the message view * * if $javascript_on is set, then the highlighting code takes * care of this; just skip it * * This code also might be more appropriate in a template file, but * we are moving this complex stuff out of the way of template * authors; advanced template sets are always free to override * the resultant values. * */ $show_label_columns = array(); $index_order_part = array(); if (!($aTemplate['javascript_on'] && $aTemplate['fancy_index_highlite'])) { $get_next_two = 0; $last_order_part = 0; $last_last_order_part = 0; foreach ($aTemplate['aOrder'] as $index_order_part) { if ($index_order_part == SQM_COL_CHECK) { $get_next_two = 1; if ($last_last_order_part != SQM_COL_SUBJ) { $show_label_columns[] = $last_last_order_part; } if ($last_order_part != SQM_COL_SUBJ) { $show_label_columns[] = $last_order_part; } } else { if ($get_next_two > 0 && $get_next_two < 3 && $index_order_part != SQM_COL_SUBJ) { $show_label_columns[] = $index_order_part; $get_next_two++; } } $last_last_order_part = $last_order_part; $last_order_part = $index_order_part; } } $aTemplate['show_label_columns'] = $show_label_columns; return $aTemplate; }
} $base_uri = sqm_baseuri(); /* * In case the last session was not terminated properly, make sure * we get a new one. */ sqsession_destroy(); header('Pragma: no-cache'); /** * This detects if the IMAP server has logins disabled, and if so, * squelches the display of the login form and puts up a message * explaining the situation. */ if ($imap_auth_mech == 'login') { $imap = sqimap_create_stream($imapServerAddress, $imapPort, $use_imap_tls); $logindisabled = sqimap_capability($imap, 'LOGINDISABLED'); sqimap_logout($imap); if ($logindisabled) { $string = _("The IMAP server is reporting that plain text logins are disabled.") . '<br />' . _("Using CRAM-MD5 or DIGEST-MD5 authentication instead may work.") . '<br />'; if (!$use_imap_tls) { $string .= _("Also, the use of TLS may allow SquirrelMail to login.") . '<br />'; } $string .= _("Please contact your system administrator and report this error."); error_box($string, $color); exit; } } do_hook('login_cookie'); /* Output the javascript onload function. */ $header = "<script language=\"JavaScript\" type=\"text/javascript\">\n" . "<!--\n" . " function squirrelmail_loginpage_onload() {\n" . " var textElements = 0;\n" . " for (i = 0; i < document.forms[0].elements.length; i++) {\n" . " if (document.forms[0].elements[i].type == \"text\" || document.forms[0].elements[i].type == \"password\") {\n" . " textElements++;\n" . " if (textElements == " . (isset($loginname) ? 2 : 1) . ") {\n" . " document.forms[0].elements[i].focus();\n" . " break;\n" . " }\n" . " }\n" . " }\n" . " }\n" . "// -->\n" . "</script>\n"; if (@file_exists($theme[$theme_default]['PATH'])) {
session_regenerate_id(); // re-send session cookie so we get the right parameters on it // (such as HTTPOnly, if necessary - PHP doesn't do this itself sqsetcookie(session_name(), session_id(), false, $base_uri); } $onetimepad = OneTimePadCreate(strlen($secretkey)); $key = OneTimePadEncrypt($secretkey, $onetimepad); sqsession_register($onetimepad, 'onetimepad'); /* remove redundant spaces */ $login_username = trim($login_username); /* Verify that username and password are correct. */ if ($force_username_lowercase) { $login_username = strtolower($login_username); } $imapConnection = sqimap_login($login_username, $key, $imapServerAddress, $imapPort, 0); $sqimap_capabilities = sqimap_capability($imapConnection); sqsession_register($sqimap_capabilities, 'sqimap_capabilities'); $delimiter = sqimap_get_delimiter($imapConnection); sqimap_logout($imapConnection); sqsession_register($delimiter, 'delimiter'); $username = $login_username; sqsession_register($username, 'username'); sqsetcookie('key', $key, 0, $base_uri); do_hook('login_verified'); } /* Set the login variables. */ $user_is_logged_in = true; $just_logged_in = true; /* And register with them with the session. */ sqsession_register($user_is_logged_in, 'user_is_logged_in'); sqsession_register($just_logged_in, 'just_logged_in');
/** * Retrieve long text string containing semi-formatted (simple text * with newlines and spaces for indentation) SquirrelMail system * specs * * @return array A three-element array, the first element containing * the string of system specs, the second one containing * a list of any warnings that may have occurred, keyed * by a warning "type" (which is used to key the corrections * array next), and the third element of which is a list * of sub-arrays keyed by warning "type": the sub-arrays * are lists of correction messages associated with the * warnings. The second and third return elements may * be empty arrays if no warnings were found. * * @since 1.5.2 * */ function get_system_specs() { //FIXME: configtest and this plugin should be using the same code to generate the basic SM system specifications and setup detection global $imapServerAddress, $username, $imapPort, $imap_server_type, $use_imap_tls, $ldap_server; // load required libraries // include_once SM_PATH . 'functions/imap_general.php'; $browscap = ini_get('browscap'); if (!empty($browscap)) { $browser = get_browser(); } $warnings = array(); $corrections = array(); sqgetGlobalVar('HTTP_USER_AGENT', $HTTP_USER_AGENT, SQ_SERVER); if (!sqgetGlobalVar('HTTP_USER_AGENT', $HTTP_USER_AGENT, SQ_SERVER)) { $HTTP_USER_AGENT = "Browser information is not available."; } $body_top = "My browser information:\n" . ' ' . $HTTP_USER_AGENT . "\n"; if (isset($browser)) { $body_top .= " get_browser() information (List)\n" . Show_Array((array) $browser); } $body_top .= "\nMy web server information:\n" . " PHP Version " . phpversion() . "\n" . " PHP Extensions (List)\n" . Show_Array(get_loaded_extensions()) . "\nSquirrelMail-specific information:\n" . " Version: " . SM_VERSION . "\n" . " Plugins (List)\n" . br_show_plugins() . "\n"; if (!empty($ldap_server[0]) && $ldap_server[0] && !extension_loaded('ldap')) { $warnings['ldap'] = "LDAP server defined in SquirrelMail config, " . "but the module is not loaded in PHP"; $corrections['ldap'][] = "Reconfigure PHP with the option '--with-ldap'"; $corrections['ldap'][] = "Then recompile PHP and reinstall"; $corrections['ldap'][] = "-- OR --"; $corrections['ldap'][] = "Reconfigure SquirrelMail to not use LDAP"; } $body = "\nMy IMAP server information:\n" . " Server type: {$imap_server_type}\n"; $imapServerAddress = sqimap_get_user_server($imapServerAddress, $username); $imap_stream = sqimap_create_stream($imapServerAddress, $imapPort, $use_imap_tls); if ($imap_stream) { $body .= ' Capabilities: '; if ($imap_capabilities = sqimap_capability($imap_stream)) { foreach ($imap_capabilities as $capability => $value) { if (is_array($value)) { foreach ($value as $val) { $body .= $capability . "={$val} "; } } else { $body .= $capability . (is_bool($value) ? ' ' : "={$value} "); } } } $body .= "\n"; sqimap_logout($imap_stream); } else { $body .= " Unable to connect to IMAP server to get information.\n"; $warnings['imap'] = "Unable to connect to IMAP server"; $corrections['imap'][] = "Make sure you specified the correct mail server"; $corrections['imap'][] = "Make sure the mail server is running IMAP, not POP"; $corrections['imap'][] = "Make sure the server responds to port {$imapPort}"; } $warning_num = 0; if (!empty($warnings)) { foreach ($warnings as $key => $value) { if ($warning_num == 0) { $body_top .= "WARNINGS WERE REPORTED WITH YOUR SETUP:\n"; $body_top = "WARNINGS WERE REPORTED WITH YOUR SETUP -- SEE BELOW\n\n{$body_top}"; } $warning_num++; $body_top .= "\n{$value}\n"; foreach ($corrections[$key] as $corr_val) { $body_top .= " * {$corr_val}\n"; } } $body_top .= "\n{$warning_num} warning(s) reported.\n"; $body_top .= "----------------------------------------------\n"; } $body = $body_top . $body; return array($body, $warnings, $corrections); }
/** * Gets the list of mailboxes for sqimap_maolbox_tree and sqimap_mailbox_list * * This is because both of those functions had duplicated logic, but with slightly different * implementations. This will make both use the same implementation, which should make it * easier to maintain and easier to modify in the future * @param stream $imap_stream imap connection resource * @param bool $force force a reload and ignore cache * @param bool $show_only_subscribed controls listing of visible or all folders * @param bool $session_register controls registration of retrieved data in session. * @return object boxesnew - array of mailboxes and their attributes * @since 1.5.1 */ function sqimap_get_mailboxes($imap_stream, $force = false, $show_only_subscribed = true, $session_register = true) { global $show_only_subscribed_folders, $noselect_fix_enable, $folder_prefix, $list_special_folders_first, $imap_server_type; $inbox_subscribed = false; $listsubscribed = sqimap_capability($imap_stream, 'LIST-SUBSCRIBED'); if ($show_only_subscribed) { $show_only_subscribed = $show_only_subscribed_folders; } //require_once(SM_PATH . 'include/load_prefs.php'); /** * There are three main listing commands we can use in IMAP: * LSUB shows just the list of subscribed folders * may include flags, but these are not necessarily accurate or authoratative * \NoSelect has special meaning: the folder does not exist -OR- it means this * folder is not subscribed but children may be * [RFC-2060] * LIST this shows every mailbox on the system * flags are always included and are accurate and authoratative * \NoSelect means folder should not be selected * [RFC-2060] * LIST (SUBSCRIBED) implemented with LIST-SUBSCRIBED extension * this is like list but returns only subscribed folders * flag meanings are like LIST, not LSUB * \NonExistent means mailbox doesn't exist * \PlaceHolder means parent is not valid (selectable), but one or more children are * \NoSelect indeed means that the folder should not be selected * IMAPEXT-LIST-EXTENSIONS-04 August 2003 B. Leiba */ if (!$show_only_subscribed) { $lsub = 'LIST'; $sub_cache_name = 'list_cache'; } elseif ($listsubscribed) { $lsub = 'LIST (SUBSCRIBED)'; $sub_cache_name = 'listsub_cache'; } else { $lsub = 'LSUB'; $sub_cache_name = 'lsub_cache'; } // Some IMAP servers allow subfolders to exist even if the parent folders do not // This fixes some problems with the folder list when this is the case, causing the // NoSelect folders to be displayed if ($noselect_fix_enable) { $lsub_args = "{$lsub} \"{$folder_prefix}\" \"*%\""; $list_args = "LIST \"{$folder_prefix}\" \"*%\""; } else { $lsub_args = "{$lsub} \"{$folder_prefix}\" \"*\""; $list_args = "LIST \"{$folder_prefix}\" \"*\""; } // get subscribed mailbox list from cache (session) // if not there, then get it from the imap server and store in cache if (!$force) { sqgetGlobalVar($sub_cache_name, $lsub_cache, SQ_SESSION); } $lsub_assoc_ary = array(); if (!empty($lsub_cache)) { $lsub_assoc_ary = $lsub_cache; } else { $lsub_ary = sqimap_run_command($imap_stream, $lsub_args, true, $response, $message); $lsub_ary = compact_mailboxes_response($lsub_ary); if (!empty($lsub_ary)) { foreach ($lsub_ary as $rawline) { $temp_mailbox_name = find_mailbox_name($rawline); $lsub_assoc_ary[$temp_mailbox_name] = $rawline; } unset($lsub_ary); sqsession_register($lsub_assoc_ary, $sub_cache_name); } } // Now to get the mailbox flags // The LSUB response may return \NoSelect flags, etc. but it is optional // according to RFC3501, and even when returned it may not be accurate // or authoratative. LIST will always return accurate results. if ($lsub == 'LIST' || $lsub == 'LIST (SUBSCRIBED)') { // we've already done a LIST or LIST (SUBSCRIBED) // and NOT a LSUB, so no need to do it again $list_assoc_ary = $lsub_assoc_ary; } else { // we did a LSUB so now we need to do a LIST // first see if it is in cache $list_cache_name = 'list_cache'; if (!$force) { sqgetGlobalVar($list_cache_name, $list_cache, SQ_SESSION); } if (!empty($list_cache)) { $list_assoc_ary = $list_cache; // we could store this in list_cache_name but not necessary } else { // not in cache so we need to go get it from the imap server $list_assoc_ary = array(); $list_ary = sqimap_run_command($imap_stream, $list_args, true, $response, $message); $list_ary = compact_mailboxes_response($list_ary); if (!empty($list_ary)) { foreach ($list_ary as $rawline) { $temp_mailbox_name = find_mailbox_name($rawline); $list_assoc_ary[$temp_mailbox_name] = $rawline; } unset($list_ary); sqsession_register($list_assoc_ary, $list_cache_name); } } } // If they aren't subscribed to the inbox, then add it anyway (if its in LIST) $inbox_subscribed = false; if (!empty($lsub_assoc_ary)) { foreach ($lsub_assoc_ary as $temp_mailbox_name => $rawline) { if (strtoupper($temp_mailbox_name) == 'INBOX') { $inbox_subscribed = true; } } } if (!$inbox_subscribed) { if (!empty($list_assoc_ary)) { foreach ($list_assoc_ary as $temp_mailbox_name => $rawline) { if (strtoupper($temp_mailbox_name) == 'INBOX') { $lsub_assoc_ary[$temp_mailbox_name] = $rawline; } } } } // Now we have the raw output, we need to create an array of mailbox names we will return if (!$show_only_subscribed) { $final_folders_assoc_ary = $list_assoc_ary; } else { /** * only show subscribed folders * we need to merge the folders here... we can't trust the flags, etc. from the lsub_assoc_array * so we use the lsub_assoc_array as the list of folders and the values come from list_assoc_array */ if (!empty($lsub_assoc_ary)) { foreach ($lsub_assoc_ary as $temp_mailbox_name => $rawline) { if (!empty($list_assoc_ary[$temp_mailbox_name])) { $final_folders_assoc_ary[$temp_mailbox_name] = $list_assoc_ary[$temp_mailbox_name]; } } } } // Now produce a flat, sorted list if (!empty($final_folders_assoc_ary)) { uksort($final_folders_assoc_ary, 'strnatcasecmp'); foreach ($final_folders_assoc_ary as $temp_mailbox_name => $rawline) { $final_folders_ary[] = $rawline; } } // this will put it into an array we can use later // containing: // raw - Raw LIST/LSUB response from the IMAP server // formatted - formatted folder name // unformatted - unformatted, but with the delimiter at the end removed // unformated-dm - folder name as it appears in raw response // unformatted-disp - unformatted without $folder_prefix // id - the array element number (0, 1, 2, etc.) // flags - mailbox flags if (!empty($final_folders_ary)) { $boxesall = sqimap_mailbox_parse($final_folders_ary); } else { // they have no mailboxes $boxesall = array(); } /* Now, lets sort for special folders */ $boxesnew = $used = array(); /* Find INBOX */ $cnt = count($boxesall); $used = array_pad($used, $cnt, false); $has_inbox = false; for ($k = 0; $k < $cnt; ++$k) { if (strtoupper($boxesall[$k]['unformatted']) == 'INBOX') { $boxesnew[] = $boxesall[$k]; $used[$k] = true; $has_inbox = true; break; } } if ($has_inbox == false) { // do a list request for inbox because we should always show // inbox even if the user isn't subscribed to it. $inbox_ary = sqimap_run_command($imap_stream, 'LIST "" "INBOX"', true, $response, $message); $inbox_ary = compact_mailboxes_response($inbox_ary); if (count($inbox_ary)) { $inbox_entry = sqimap_mailbox_parse($inbox_ary); // add it on top of the list if (!empty($boxesnew)) { array_unshift($boxesnew, $inbox_entry[0]); } else { $boxesnew[] = $inbox_entry[0]; } /* array_unshift($used,true); */ } } /* List special folders and their subfolders, if requested. */ if ($list_special_folders_first) { for ($k = 0; $k < $cnt; ++$k) { if (!$used[$k] && isSpecialMailbox($boxesall[$k]['unformatted'])) { $boxesnew[] = $boxesall[$k]; $used[$k] = true; } } } /* Find INBOX's children */ for ($k = 0; $k < $cnt; ++$k) { $isboxbelow = isBoxBelow(strtoupper($boxesall[$k]['unformatted']), 'INBOX'); if (strtoupper($boxesall[$k]['unformatted']) == 'INBOX') { $is_inbox = 1; } else { $is_inbox = 0; } if (!$used[$k] && $isboxbelow && $is_inbox) { $boxesnew[] = $boxesall[$k]; $used[$k] = true; } } /* Rest of the folders */ for ($k = 0; $k < $cnt; $k++) { if (!$used[$k]) { $boxesnew[] = $boxesall[$k]; } } /** * Don't register boxes in session, if $session_register is set to false * Prevents registration of sqimap_mailbox_list_all() results. */ if ($session_register) { sqsession_register($boxesnew, 'boxesnew'); } return $boxesnew; }
/** * Returns sorted mailbox lists in several different ways. * See comment on sqimap_mailbox_parse() for info about the returned array. */ function sqimap_mailbox_list($imap_stream, $force = false) { global $default_folder_prefix; if (!sqgetGlobalVar('boxesnew', $boxesnew, SQ_SESSION) || $force) { global $data_dir, $username, $list_special_folders_first, $folder_prefix, $trash_folder, $sent_folder, $draft_folder, $move_to_trash, $move_to_sent, $save_as_draft, $delimiter, $noselect_fix_enable, $imap_server_type; $inbox_in_list = false; $inbox_subscribed = false; $listsubscribed = sqimap_capability($imap_stream, 'LIST-SUBSCRIBED'); require_once SM_PATH . 'include/load_prefs.php'; if ($listsubscribed) { $lsub = 'LIST (SUBSCRIBED)'; } else { $lsub = 'LSUB'; } if ($noselect_fix_enable) { $lsub_args = "{$lsub} \"{$folder_prefix}\" \"*%\""; } else { $lsub_args = "{$lsub} \"{$folder_prefix}\" \"*\""; } /* LSUB array */ $lsub_ary = sqimap_run_command($imap_stream, $lsub_args, true, $response, $message); $lsub_ary = compact_mailboxes_response($lsub_ary); $sorted_lsub_ary = array(); for ($i = 0, $cnt = count($lsub_ary); $i < $cnt; $i++) { $temp_mailbox_name = find_mailbox_name($lsub_ary[$i]); $sorted_lsub_ary[] = $temp_mailbox_name; if (!$inbox_subscribed && strtoupper($temp_mailbox_name) == 'INBOX') { $inbox_subscribed = true; } } /* natural sort mailboxes */ if (isset($sorted_lsub_ary)) { usort($sorted_lsub_ary, 'strnatcasecmp'); } /* * The LSUB response doesn't provide us information about \Noselect * mail boxes. The LIST response does, that's why we need to do a LIST * call to retrieve the flags for the mailbox * Note: according RFC2060 an imap server may provide \NoSelect flags in the LSUB response. * in other words, we cannot rely on it. */ $sorted_list_ary = array(); // if (!$listsubscribed) { for ($i = 0; $i < count($sorted_lsub_ary); $i++) { if (substr($sorted_lsub_ary[$i], -1) == $delimiter) { $mbx = substr($sorted_lsub_ary[$i], 0, strlen($sorted_lsub_ary[$i]) - 1); } else { $mbx = $sorted_lsub_ary[$i]; } $read = sqimap_run_command($imap_stream, 'LIST "" ' . sqimap_encode_mailbox_name($mbx), true, $response, $message); $read = compact_mailboxes_response($read); if (isset($read[0])) { $sorted_list_ary[$i] = $read[0]; } else { $sorted_list_ary[$i] = ''; } } // } /* * Just in case they're not subscribed to their inbox, * we'll get it for them anyway */ if (!$inbox_subscribed) { $inbox_ary = sqimap_run_command($imap_stream, 'LIST "" "INBOX"', true, $response, $message); $sorted_list_ary[] = implode('', compact_mailboxes_response($inbox_ary)); $sorted_lsub_ary[] = find_mailbox_name($inbox_ary[0]); } $boxesall = sqimap_mailbox_parse($sorted_list_ary, $sorted_lsub_ary); /* Now, lets sort for special folders */ $boxesnew = $used = array(); /* Find INBOX */ $cnt = count($boxesall); $used = array_pad($used, $cnt, false); for ($k = 0; $k < $cnt; ++$k) { if (strtolower($boxesall[$k]['unformatted']) == 'inbox') { $boxesnew[] = $boxesall[$k]; $used[$k] = true; break; } } /* List special folders and their subfolders, if requested. */ if ($list_special_folders_first) { for ($k = 0; $k < $cnt; ++$k) { if (!$used[$k] && isSpecialMailbox($boxesall[$k]['unformatted'])) { $boxesnew[] = $boxesall[$k]; $used[$k] = true; } } } /* Rest of the folders */ for ($k = 0; $k < $cnt; $k++) { if (!$used[$k]) { $boxesnew[] = $boxesall[$k]; } } sqsession_register($boxesnew, 'boxesnew'); } return $boxesnew; }
/** * Returns the delimiter between mailboxes: INBOX/Test, or INBOX.Test * @param stream $imap_stream * @return string */ function sqimap_get_delimiter($imap_stream = false) { global $sqimap_delimiter, $optional_delimiter; /* Use configured delimiter if set */ if (!empty($optional_delimiter) && $optional_delimiter != 'detect') { return $optional_delimiter; } /* Delimiter is stored in the session from redirect. Try fetching from there first */ if (empty($sqimap_delimiter)) { sqgetGlobalVar('delimiter', $sqimap_delimiter, SQ_SESSION); } /* Do some caching here */ if (!$sqimap_delimiter) { if (sqimap_capability($imap_stream, 'NAMESPACE') && ($read = sqimap_run_command($imap_stream, 'NAMESPACE', true, $a, $b)) && preg_match('/\\* NAMESPACE +(\\( *\\(.+\\) *\\)|NIL) +(\\( *\\(.+\\) *\\)|NIL) +(\\( *\\(.+\\) *\\)|NIL)/i', $read[0], $data) && preg_match('/^\\( *\\((.*)\\) *\\)/', $data[1], $data2)) { $pn = $data2[1]; $pna = explode(')(', $pn); $delnew = array(); while (list($k, $v) = each($pna)) { $lst = explode('"', $v); if (isset($lst[3])) { $delnew[$lst[1]] = $lst[3]; } else { $delnew[$lst[1]] = ''; } } $sqimap_delimiter = array_shift($delnew); } else { fputs($imap_stream, ". LIST \"INBOX\" \"\"\r\n"); $read = sqimap_read_data($imap_stream, '.', true, $a, $b); $read = $read['.'][0]; //sqimap_read_data() now returns a tag array of response array $quote_position = strpos($read[0], '"'); $sqimap_delimiter = substr($read[0], $quote_position + 1, 1); } } return $sqimap_delimiter; }