Ejemplo n.º 1
0
/**
 * 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;
}
Ejemplo n.º 2
0
function sqimap_mailbox_tree($imap_stream)
{
    global $default_folder_prefix, $unseen_notify, $unseen_type;
    if (true) {
        global $data_dir, $username, $list_special_folders_first, $folder_prefix, $delimiter, $trash_folder, $move_to_trash, $imap_server_type;
        $inbox_in_list = false;
        $inbox_subscribed = false;
        $noselect = false;
        $noinferiors = false;
        require_once SM_PATH . 'include/load_prefs.php';
        /* LSUB array */
        $lsub_ary = sqimap_run_command($imap_stream, "LSUB \"{$folder_prefix}\" \"*\"", true, $response, $message);
        $lsub_ary = compact_mailboxes_response($lsub_ary);
        /* Check to see if we have an INBOX */
        $has_inbox = false;
        for ($i = 0, $cnt = count($lsub_ary); $i < $cnt; $i++) {
            if (preg_match("/^\\*\\s+LSUB.*\\s\"?INBOX\"?[^(\\/\\.)].*\$/i", $lsub_ary[$i])) {
                $lsub_ary[$i] = strtoupper($lsub_ary[$i]);
                // in case of an unsubscribed inbox an imap server can
                // return the inbox in the lsub results with a \NoSelect
                // flag.
                if (!preg_match("/\\*\\s+LSUB\\s+\\(.*\\\\NoSelect.*\\).*/i", $lsub_ary[$i])) {
                    $has_inbox = true;
                } else {
                    // remove the result and request it again  with a list
                    // response at a later stage.
                    unset($lsub_ary[$i]);
                    // re-index the array otherwise the addition of the LIST
                    // response will fail in PHP 4.1.2 and probably other older versions
                    $lsub_ary = array_values($lsub_ary);
                }
                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)) {
                $lsub_ary[] = $inbox_ary[0];
            }
        }
        /*
         * Section about removing the last element was removed
         * We don't return "* OK" anymore from sqimap_read_data
         */
        $sorted_lsub_ary = array();
        $cnt = count($lsub_ary);
        for ($i = 0; $i < $cnt; $i++) {
            $mbx = find_mailbox_name($lsub_ary[$i]);
            // only do the noselect test if !uw, is checked later. FIX ME see conf.pl setting
            if ($imap_server_type != "uw") {
                $noselect = check_is_noselect($lsub_ary[$i]);
                $noinferiors = check_is_noinferiors($lsub_ary[$i]);
            }
            if (substr($mbx, -1) == $delimiter) {
                $mbx = substr($mbx, 0, strlen($mbx) - 1);
            }
            $sorted_lsub_ary[] = array('mbx' => $mbx, 'noselect' => $noselect, 'noinferiors' => $noinferiors);
        }
        // FIX ME this requires a config setting inside conf.pl instead of checking on server type
        if ($imap_server_type == "uw") {
            $aQuery = array();
            $aTag = array();
            // prepare an array with queries
            foreach ($sorted_lsub_ary as $aMbx) {
                $mbx = stripslashes($aMbx['mbx']);
                sqimap_prepare_pipelined_query('LIST "" ' . sqimap_encode_mailbox_name($mbx), $tag, $aQuery, false);
                $aTag[$tag] = $mbx;
            }
            $sorted_lsub_ary = array();
            // execute all the queries at once
            $aResponse = sqimap_run_pipelined_command($imap_stream, $aQuery, false, $aServerResponse, $aServerMessage);
            foreach ($aTag as $tag => $mbx) {
                if ($aServerResponse[$tag] == 'OK') {
                    $sResponse = implode('', $aResponse[$tag]);
                    $noselect = check_is_noselect($sResponse);
                    $noinferiors = check_is_noinferiors($sResponse);
                    $sorted_lsub_ary[] = array('mbx' => $mbx, 'noselect' => $noselect, 'noinferiors' => $noinferiors);
                }
            }
            $cnt = count($sorted_lsub_ary);
        }
        $sorted_lsub_ary = array_values($sorted_lsub_ary);
        usort($sorted_lsub_ary, 'mbxSort');
        $boxestree = sqimap_fill_mailbox_tree($sorted_lsub_ary, false, $imap_stream);
        return $boxestree;
    }
}