function sqimap_login($username, $password, $imap_server_address, $imap_port, $hide)
{
    global $color, $squirrelmail_language, $onetimepad, $use_imap_tls, $imap_auth_mech;
    if (!isset($onetimepad) || empty($onetimepad)) {
        sqgetglobalvar('onetimepad', $onetimepad, SQ_SESSION);
    }
    $imap_server_address = sqimap_get_user_server($imap_server_address, $username);
    $host = $imap_server_address;
    if ($use_imap_tls == true and check_php_version(4, 3) and extension_loaded('openssl')) {
        /* Use TLS by prefixing "tls://" to the hostname */
        $imap_server_address = 'tls://' . $imap_server_address;
    }
    $imap_stream = fsockopen($imap_server_address, $imap_port, $error_number, $error_string, 15);
    /* Do some error correction */
    if (!$imap_stream) {
        if (!$hide) {
            set_up_language($squirrelmail_language, true);
            require_once SM_PATH . 'functions/display_messages.php';
            $string = sprintf(_("Error connecting to IMAP server: %s.") . "<br>\r\n", $imap_server_address) . "{$error_number} : {$error_string}<br>\r\n";
            logout_error($string, $color);
        }
        exit;
    }
    $server_info = fgets($imap_stream, 1024);
    /* Decrypt the password */
    $password = OneTimePadDecrypt($password, $onetimepad);
    if ($imap_auth_mech == 'cram-md5' or $imap_auth_mech == 'digest-md5') {
        // We're using some sort of authentication OTHER than plain or login
        $tag = sqimap_session_id(false);
        if ($imap_auth_mech == 'digest-md5') {
            $query = $tag . " AUTHENTICATE DIGEST-MD5\r\n";
        } elseif ($imap_auth_mech == 'cram-md5') {
            $query = $tag . " AUTHENTICATE CRAM-MD5\r\n";
        }
        fputs($imap_stream, $query);
        $answer = sqimap_fgets($imap_stream);
        // Trim the "+ " off the front
        $response = explode(" ", $answer, 3);
        if ($response[0] == '+') {
            // Got a challenge back
            $challenge = $response[1];
            if ($imap_auth_mech == 'digest-md5') {
                $reply = digest_md5_response($username, $password, $challenge, 'imap', $host);
            } elseif ($imap_auth_mech == 'cram-md5') {
                $reply = cram_md5_response($username, $password, $challenge);
            }
            fputs($imap_stream, $reply);
            $read = sqimap_fgets($imap_stream);
            if ($imap_auth_mech == 'digest-md5') {
                // DIGEST-MD5 has an extra step..
                if (substr($read, 0, 1) == '+') {
                    // OK so far..
                    fputs($imap_stream, "\r\n");
                    $read = sqimap_fgets($imap_stream);
                }
            }
            $results = explode(" ", $read, 3);
            $response = $results[1];
            $message = $results[2];
        } else {
            // Fake the response, so the error trap at the bottom will work
            $response = "BAD";
            $message = 'IMAP server does not appear to support the authentication method selected.';
            $message .= '  Please contact your system administrator.';
        }
    } elseif ($imap_auth_mech == 'login') {
        // Original IMAP login code
        $query = 'LOGIN "' . quoteimap($username) . '" "' . quoteimap($password) . '"';
        $read = sqimap_run_command($imap_stream, $query, false, $response, $message);
    } elseif ($imap_auth_mech == 'plain') {
        /* Replace this with SASL PLAIN if it ever gets implemented */
        $response = "BAD";
        $message = 'SquirrelMail does not support SASL PLAIN yet. Rerun conf.pl and use login instead.';
    } else {
        $response = "BAD";
        $message = "Internal SquirrelMail error - unknown IMAP authentication method chosen.  Please contact the developers.";
    }
    /* If the connection was not successful, lets see why */
    if ($response != 'OK') {
        if (!$hide) {
            if ($response != 'NO') {
                /* "BAD" and anything else gets reported here. */
                $message = htmlspecialchars($message);
                set_up_language($squirrelmail_language, true);
                require_once SM_PATH . 'functions/display_messages.php';
                if ($response == 'BAD') {
                    $string = sprintf(_("Bad request: %s") . "<br>\r\n", $message);
                } else {
                    $string = sprintf(_("Unknown error: %s") . "<br>\n", $message);
                }
                if (isset($read) && is_array($read)) {
                    $string .= '<br>' . _("Read data:") . "<br>\n";
                    foreach ($read as $line) {
                        $string .= htmlspecialchars($line) . "<br>\n";
                    }
                }
                error_box($string, $color);
                exit;
            } else {
                /*
                 * If the user does not log in with the correct
                 * username and password it is not possible to get the
                 * correct locale from the user's preferences.
                 * Therefore, apply the same hack as on the login
                 * screen.
                 *
                 * $squirrelmail_language is set by a cookie when
                 * the user selects language and logs out
                 */
                set_up_language($squirrelmail_language, true);
                include_once SM_PATH . 'functions/display_messages.php';
                sqsession_destroy();
                logout_error(_("Unknown user or password incorrect."));
                exit;
            }
        } else {
            exit;
        }
    }
    return $imap_stream;
}
/**
 * Logs the user into the imap server.  If $hide is set, no error messages
 * will be displayed.  This function returns the imap connection handle.
 */
function sqimap_login($username, $password, $imap_server_address, $imap_port, $hide)
{
    global $color, $squirrelmail_language, $onetimepad, $use_imap_tls, $imap_auth_mech, $sqimap_capabilities;
    if (!isset($onetimepad) || empty($onetimepad)) {
        sqgetglobalvar('onetimepad', $onetimepad, SQ_SESSION);
    }
    if (!isset($sqimap_capabilities)) {
        sqgetglobalvar('sqimap_capabilities', $capability, SQ_SESSION);
    }
    $host = $imap_server_address;
    $imap_server_address = sqimap_get_user_server($imap_server_address, $username);
    $imap_stream = sqimap_create_stream($imap_server_address, $imap_port, $use_imap_tls);
    /* Decrypt the password */
    //$password = OneTimePadDecrypt($password, $onetimepad);
    if ($imap_auth_mech == 'cram-md5' or $imap_auth_mech == 'digest-md5') {
        // We're using some sort of authentication OTHER than plain or login
        $tag = sqimap_session_id(false);
        if ($imap_auth_mech == 'digest-md5') {
            $query = $tag . " AUTHENTICATE DIGEST-MD5\r\n";
        } elseif ($imap_auth_mech == 'cram-md5') {
            $query = $tag . " AUTHENTICATE CRAM-MD5\r\n";
        }
        fputs($imap_stream, $query);
        $answer = sqimap_fgets($imap_stream);
        // Trim the "+ " off the front
        $response = explode(" ", $answer, 3);
        if ($response[0] == '+') {
            // Got a challenge back
            $challenge = $response[1];
            if ($imap_auth_mech == 'digest-md5') {
                $reply = digest_md5_response($username, $password, $challenge, 'imap', $host);
            } elseif ($imap_auth_mech == 'cram-md5') {
                $reply = cram_md5_response($username, $password, $challenge);
            }
            fputs($imap_stream, $reply);
            $read = sqimap_fgets($imap_stream);
            if ($imap_auth_mech == 'digest-md5') {
                // DIGEST-MD5 has an extra step..
                if (substr($read, 0, 1) == '+') {
                    // OK so far..
                    fputs($imap_stream, "\r\n");
                    $read = sqimap_fgets($imap_stream);
                }
            }
            $results = explode(" ", $read, 3);
            $response = $results[1];
            $message = $results[2];
        } else {
            // Fake the response, so the error trap at the bottom will work
            $response = "BAD";
            $message = 'IMAP server does not appear to support the authentication method selected.';
            $message .= '  Please contact your system administrator.';
        }
    } elseif ($imap_auth_mech == 'login') {
        // Original IMAP login code
        $query = 'LOGIN "' . quoteimap($username) . '" "' . quoteimap($password) . '"';
        $read = sqimap_run_command($imap_stream, $query, false, $response, $message);
    } elseif ($imap_auth_mech == 'plain') {
        /***
         * SASL PLAIN
         *
         *  RFC 2595 Chapter 6
         *
         *  The mechanism consists of a single message from the client to the
         *  server.  The client sends the authorization identity (identity to
         *  login as), followed by a US-ASCII NUL character, followed by the
         *  authentication identity (identity whose password will be used),
         *  followed by a US-ASCII NUL character, followed by the clear-text
         *  password.  The client may leave the authorization identity empty to
         *  indicate that it is the same as the authentication identity.
         *
         **/
        $tag = sqimap_session_id(false);
        $sasl = isset($capability['SASL-IR']) && $capability['SASL-IR'] ? true : false;
        $auth = base64_encode("{$username}{$username}{$password}");
        if ($sasl) {
            // IMAP Extension for SASL Initial Client Response
            // <draft-siemborski-imap-sasl-initial-response-01b.txt>
            $query = $tag . " AUTHENTICATE PLAIN {$auth}\r\n";
            fputs($imap_stream, $query);
            $read = sqimap_fgets($imap_stream);
        } else {
            $query = $tag . " AUTHENTICATE PLAIN\r\n";
            fputs($imap_stream, $query);
            $read = sqimap_fgets($imap_stream);
            if (substr($read, 0, 1) == '+') {
                // OK so far..
                fputs($imap_stream, "{$auth}\r\n");
                $read = sqimap_fgets($imap_stream);
            }
        }
        $results = explode(" ", $read, 3);
        $response = $results[1];
        $message = $results[2];
    } else {
        $response = "BAD";
        $message = "Internal SquirrelMail error - unknown IMAP authentication method chosen.  Please contact the developers.";
    }
    /* If the connection was not successful, lets see why */
    if ($response != 'OK') {
        if (!$hide) {
            if ($response != 'NO') {
                /* "BAD" and anything else gets reported here. */
                $message = htmlspecialchars($message);
                set_up_language($squirrelmail_language, true);
                require_once SM_PATH . 'functions/display_messages.php';
                if ($response == 'BAD') {
                    $string = sprintf(_("Bad request: %s") . "<br />\r\n", $message);
                } else {
                    $string = sprintf(_("Unknown error: %s") . "<br />\n", $message);
                }
                if (isset($read) && is_array($read)) {
                    $string .= '<br />' . _("Read data:") . "<br />\n";
                    foreach ($read as $line) {
                        $string .= htmlspecialchars($line) . "<br />\n";
                    }
                }
                error_box($string, $color);
                exit;
            } else {
                /*
                 * If the user does not log in with the correct
                 * username and password it is not possible to get the
                 * correct locale from the user's preferences.
                 * Therefore, apply the same hack as on the login
                 * screen.
                 *
                 * $squirrelmail_language is set by a cookie when
                 * the user selects language and logs out
                 */
                set_up_language($squirrelmail_language, true);
                include_once SM_PATH . 'functions/display_messages.php';
                sqsession_destroy();
                /* terminate the session nicely */
                sqimap_logout($imap_stream);
                logout_error(_("Unknown user or password incorrect."));
                exit;
            }
        } else {
            exit;
        }
    }
    return $imap_stream;
}
Exemple #3
0
/**
 * Creates and runs the IMAP command to filter messages
 * @param string $imap_stream TODO: Document this parameter
 * @param string $where Which part of the message to search (TO, CC, SUBJECT, etc...)
 * @param string $what String to search for
 * @param string $where_to Folder it will move to
 * @param string $user_scan Whether to search all or just unseen
 * @param string $should_expunge
 * @access private
 */
function filter_search_and_delete($imap_stream, $where, $what, $where_to, $user_scan, $should_expunge)
{
    global $languages, $squirrelmail_language, $allow_charset_search, $imap_server_type;
    //TODO: make use of new mailbox cache. See mailbox_display.phpinfo
    if (strtolower($where_to) == 'inbox') {
        return array();
    }
    if ($user_scan == 'new') {
        $category = 'UNSEEN';
    } else {
        $category = 'ALL';
    }
    $category .= ' UNDELETED';
    if ($allow_charset_search && isset($languages[$squirrelmail_language]['CHARSET']) && $languages[$squirrelmail_language]['CHARSET']) {
        $search_str = 'SEARCH CHARSET ' . strtoupper($languages[$squirrelmail_language]['CHARSET']) . ' ' . $category;
    } else {
        $search_str = 'SEARCH CHARSET US-ASCII ' . $category;
    }
    if ($where == 'Header') {
        $what = explode(':', $what);
        $where = strtoupper($where);
        $where = trim($where . ' ' . $what[0]);
        $what = addslashes(trim($what[1]));
    }
    // see comments in squirrelmail sqimap_search function
    if ($imap_server_type == 'macosx' || $imap_server_type == 'hmailserver') {
        $search_str .= ' ' . $where . ' ' . $what;
        /* read data back from IMAP */
        $read = sqimap_run_command($imap_stream, $search_str, true, $response, $message, TRUE);
    } else {
        $search_str .= ' ' . $where . ' {' . strlen($what) . "}";
        $sid = sqimap_session_id(true);
        fputs($imap_stream, $sid . ' ' . $search_str . "\r\n");
        $read2 = sqimap_fgets($imap_stream);
        # server should respond with Ready for argument, then we will send search text
        #echo "RR2 $read2<br>";
        fputs($imap_stream, "{$what}\r\n");
        #echo "SS $what<br>";
        $read2 = sqimap_fgets($imap_stream);
        #echo "RR2 $read2<br>";
        $read[] = $read2;
        $read3 = sqimap_fgets($imap_stream);
        #echo "RR3 $read3<br>";
        list($rtag, $response, $message) = explode(' ', $read3, 3);
        ##        $read2 = sqimap_retrieve_imap_response($imap_stream, $sid, true,
        ##              $response, $message, $search_str, false, true, false);
        #echo "RR2 $read2 / RESPONSE $response<br>";
    }
    if (isset($read[0])) {
        $ids = array();
        for ($i = 0, $iCnt = count($read); $i < $iCnt; ++$i) {
            if (preg_match("/^\\* SEARCH (.+)\$/", $read[$i], $regs)) {
                $ids += explode(' ', trim($regs[1]));
            }
        }
        if ($response == 'OK' && count($ids)) {
            if (sqimap_mailbox_exists($imap_stream, $where_to)) {
                if (!sqimap_msgs_list_move($imap_stream, $ids, $where_to, false)) {
                    // if errors occurred, don't try to filter again during this session
                    sqsession_register(TRUE, 'filters_error');
                    global $color;
                    error_box(_("A problem occurred filtering messages. Check filter settings and account quota if applicable. Filtering is disabled for the remainder of this login session."), $color);
                }
                // expunge even in the case of errors, in case some
                // messages were filtered before the error happened
                $should_expunge = true;
            }
        } elseif ($response != 'OK') {
            $query = $search_str . "\r\n" . $what . "\r\n";
            if ($response == 'NO') {
                if (strpos($message, 'BADCHARSET') !== false || strpos($message, 'character') !== false) {
                    sqm_trigger_imap_error('SQM_IMAP_BADCHARSET', $query, $response, $message);
                } else {
                    sqm_trigger_imap_error('SQM_IMAP_ERROR', $query, $response, $message);
                }
            } else {
                sqm_trigger_imap_error('SQM_IMAP_ERROR', $query, $response, $message);
            }
        }
    }
    return $should_expunge;
}
/**
 * Logs the user into the IMAP server.  If $hide is set, no error messages
 * will be displayed (if set to 1, just exits, if set to 2, returns FALSE).
 * This function returns the IMAP connection handle.
 * @param string $username user name
 * @param string $password password encrypted with onetimepad. Since 1.5.2
 *  function can use internal password functions, if parameter is set to
 *  boolean false.
 * @param string $imap_server_address address of imap server
 * @param integer $imap_port port of imap server
 * @param int $hide controls display connection errors:
 *                  0 = do not hide
 *                  1 = show no errors (just exit)
 *                  2 = show no errors (return FALSE)
 *                  3 = show no errors (return error string)
 * @param array $stream_options Stream context options, see config_local.php
 *                           for more details (OPTIONAL)
 * @return mixed The IMAP connection stream, or if the connection fails,
 *               FALSE if $hide is set to 2 or an error string if $hide
 *               is set to 3.
 */
function sqimap_login($username, $password, $imap_server_address, $imap_port, $hide, $stream_options = array())
{
    global $color, $squirrelmail_language, $onetimepad, $use_imap_tls, $imap_auth_mech, $sqimap_capabilities, $display_imap_login_error;
    // Note/TODO: This hack grabs the $authz argument from the session. In the short future,
    // a new argument in function sqimap_login() will be used instead.
    $authz = '';
    global $authz;
    sqgetglobalvar('authz', $authz, SQ_SESSION);
    if (!empty($authz)) {
        /* authz plugin - specific:
         * Get proxy login parameters from authz plugin configuration. If they
         * exist, they will override the current ones.
         * This is useful if we want to use different SASL authentication mechanism
         * and/or different TLS settings for proxy logins. */
        global $authz_imap_auth_mech, $authz_use_imap_tls, $authz_imapPort_tls;
        $imap_auth_mech = !empty($authz_imap_auth_mech) ? strtolower($authz_imap_auth_mech) : $imap_auth_mech;
        $use_imap_tls = !empty($authz_use_imap_tls) ? $authz_use_imap_tls : $use_imap_tls;
        $imap_port = !empty($authz_use_imap_tls) ? $authz_imapPort_tls : $imap_port;
        if ($imap_auth_mech == 'login' || $imap_auth_mech == 'cram-md5') {
            logout_error("Misconfigured Plugin (authz or equivalent):<br/>" . "The LOGIN and CRAM-MD5 authentication mechanisms cannot be used when attempting proxy login.");
            exit;
        }
    }
    /* get imap login password */
    if ($password === false) {
        /* standard functions */
        $password = sqauth_read_password();
    } else {
        /* old way. $key must be extracted from cookie */
        if (!isset($onetimepad) || empty($onetimepad)) {
            sqgetglobalvar('onetimepad', $onetimepad, SQ_SESSION);
        }
        /* Decrypt the password */
        $password = OneTimePadDecrypt($password, $onetimepad);
    }
    if (!isset($sqimap_capabilities)) {
        sqgetglobalvar('sqimap_capabilities', $sqimap_capabilities, SQ_SESSION);
    }
    $host = $imap_server_address;
    $imap_server_address = sqimap_get_user_server($imap_server_address, $username);
    $imap_stream = sqimap_create_stream($imap_server_address, $imap_port, $use_imap_tls, $stream_options);
    if ($imap_auth_mech == 'cram-md5' or $imap_auth_mech == 'digest-md5') {
        // We're using some sort of authentication OTHER than plain or login
        $tag = sqimap_session_id(false);
        if ($imap_auth_mech == 'digest-md5') {
            $query = $tag . " AUTHENTICATE DIGEST-MD5\r\n";
        } elseif ($imap_auth_mech == 'cram-md5') {
            $query = $tag . " AUTHENTICATE CRAM-MD5\r\n";
        }
        fputs($imap_stream, $query);
        $answer = sqimap_fgets($imap_stream);
        // Trim the "+ " off the front
        $response = explode(" ", $answer, 3);
        if ($response[0] == '+') {
            // Got a challenge back
            $challenge = $response[1];
            if ($imap_auth_mech == 'digest-md5') {
                $reply = digest_md5_response($username, $password, $challenge, 'imap', $host, $authz);
            } elseif ($imap_auth_mech == 'cram-md5') {
                $reply = cram_md5_response($username, $password, $challenge);
            }
            fputs($imap_stream, $reply);
            $read = sqimap_fgets($imap_stream);
            if ($imap_auth_mech == 'digest-md5') {
                // DIGEST-MD5 has an extra step..
                if (substr($read, 0, 1) == '+') {
                    // OK so far..
                    fputs($imap_stream, "\r\n");
                    $read = sqimap_fgets($imap_stream);
                }
            }
            $results = explode(" ", $read, 3);
            $response = $results[1];
            $message = $results[2];
        } else {
            // Fake the response, so the error trap at the bottom will work
            $response = "BAD";
            $message = 'IMAP server does not appear to support the authentication method selected.';
            $message .= '  Please contact your system administrator.';
        }
    } elseif ($imap_auth_mech == 'login') {
        // Original IMAP login code
        $query = 'LOGIN "' . quoteimap($username) . '" "' . quoteimap($password) . '"';
        $read = sqimap_run_command($imap_stream, $query, false, $response, $message);
    } elseif ($imap_auth_mech == 'plain') {
        /***
         * SASL PLAIN, RFC 4616 (updates 2595)
         *
         * The mechanism consists of a single message, a string of [UTF-8]
         * encoded [Unicode] characters, from the client to the server.  The
         * client presents the authorization identity (identity to act as),
         * followed by a NUL (U+0000) character, followed by the authentication
         * identity (identity whose password will be used), followed by a NUL
         * (U+0000) character, followed by the clear-text password.  As with
         * other SASL mechanisms, the client does not provide an authorization
         * identity when it wishes the server to derive an identity from the
         * 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;
        if (!empty($authz)) {
            $auth = base64_encode("{$username}{$authz}{$password}");
        } else {
            $auth = base64_encode("{$username}{$username}{$password}");
        }
        if ($sasl) {
            // IMAP Extension for SASL Initial Client Response
            // <draft-siemborski-imap-sasl-initial-response-01b.txt>
            $query = $tag . " AUTHENTICATE PLAIN {$auth}\r\n";
            fputs($imap_stream, $query);
            $read = sqimap_fgets($imap_stream);
        } else {
            $query = $tag . " AUTHENTICATE PLAIN\r\n";
            fputs($imap_stream, $query);
            $read = sqimap_fgets($imap_stream);
            if (substr($read, 0, 1) == '+') {
                // OK so far..
                fputs($imap_stream, "{$auth}\r\n");
                $read = sqimap_fgets($imap_stream);
            }
        }
        $results = explode(" ", $read, 3);
        $response = $results[1];
        $message = $results[2];
    } else {
        $response = "BAD";
        $message = "Internal SquirrelMail error - unknown IMAP authentication method chosen.  Please contact the developers.";
    }
    /* If the connection was not successful, lets see why */
    if ($response != 'OK') {
        if (!$hide || $hide == 3) {
            //FIXME: UUURG... We don't want HTML in error messages, should also do html sanitizing of error messages elsewhere; should't assume output is destined for an HTML browser here
            if ($response != 'NO') {
                /* "BAD" and anything else gets reported here. */
                $message = sm_encode_html_special_chars($message);
                set_up_language($squirrelmail_language, true);
                if ($response == 'BAD') {
                    if ($hide == 3) {
                        return sprintf(_("Bad request: %s"), $message);
                    }
                    $string = sprintf(_("Bad request: %s") . "<br />\r\n", $message);
                } else {
                    if ($hide == 3) {
                        return sprintf(_("Unknown error: %s"), $message);
                    }
                    $string = sprintf(_("Unknown error: %s") . "<br />\n", $message);
                }
                if (isset($read) && is_array($read)) {
                    $string .= '<br />' . _("Read data:") . "<br />\n";
                    foreach ($read as $line) {
                        $string .= sm_encode_html_special_chars($line) . "<br />\n";
                    }
                }
                error_box($string);
                exit;
            } else {
                /*
                 * If the user does not log in with the correct
                 * username and password it is not possible to get the
                 * correct locale from the user's preferences.
                 * Therefore, apply the same hack as on the login
                 * screen.
                 *
                 * $squirrelmail_language is set by a cookie when
                 * the user selects language and logs out
                 */
                set_up_language($squirrelmail_language, true);
                sqsession_destroy();
                /* terminate the session nicely */
                sqimap_logout($imap_stream);
                // determine what error message to use
                //
                $fail_msg = _("Unknown user or password incorrect.");
                if ($display_imap_login_error) {
                    // See if there is an error message from the server
                    // Skip any rfc5530 response code: '[something]' at the
                    // start of the message
                    if (!empty($message) && $message[0] == '[' && ($end = strstr($message, ']')) && $end != ']') {
                        $message = substr($end, 1);
                    }
                    // Remove surrounding spaces and if there
                    // is anything left, display that as the
                    // error message:
                    $message = trim($message);
                    if (strlen($message)) {
                        $fail_msg = _($message);
                    }
                }
                if ($hide == 3) {
                    return $fail_msg;
                }
                logout_error($fail_msg);
                exit;
            }
        } else {
            if ($hide == 2) {
                return FALSE;
            }
            exit;
        }
    }
    /* Special error case:
     * Login referrals. The server returns:
     * ? OK [REFERRAL <imap url>]
     * Check RFC 2221 for details. Since we do not support login referrals yet
     * we log the user out.
     */
    if (stristr($message, 'REFERRAL imap') === TRUE) {
        sqimap_logout($imap_stream);
        set_up_language($squirrelmail_language, true);
        sqsession_destroy();
        logout_error(_("Your mailbox is not located at this server. Try a different server or consult your system administrator"));
        exit;
    }
    return $imap_stream;
}
function sqimap_read_data_list($imap_stream, $tag_uid, $handle_errors, &$response, &$message, $query = '', $filter = false, $outputstream = false, $no_return = false)
{
    $read = '';
    $tag_uid_a = explode(' ', trim($tag_uid));
    $tag = $tag_uid_a[0];
    $resultlist = array();
    $data = array();
    $read = sqimap_fgets($imap_stream);
    $i = 0;
    while ($read) {
        $char = substr($read, 0, 1);
        switch ($char) {
            case '+':
            default:
                $read = sqimap_fgets($imap_stream);
                break;
            case substr($tag, 0, 1):
                /* get the command */
                $arg = '';
                $i = strlen($tag) + 1;
                $s = substr($read, $i);
                if (($j = strpos($s, ' ')) || ($j = strpos($s, "\n"))) {
                    $arg = substr($s, 0, $j);
                }
                $found_tag = substr($read, 0, $i - 1);
                if ($arg && $found_tag == $tag) {
                    switch ($arg) {
                        case 'OK':
                        case 'BAD':
                        case 'NO':
                        case 'BYE':
                        case 'PREAUTH':
                            $response = $arg;
                            $message = trim(substr($read, $i + strlen($arg)));
                            break 3;
                            /* switch switch while */
                        /* switch switch while */
                        default:
                            /* this shouldn't happen */
                            $response = $arg;
                            $message = trim(substr($read, $i + strlen($arg)));
                            break 3;
                            /* switch switch while */
                    }
                } elseif ($found_tag !== $tag) {
                    /* reset data array because we do not need this reponse */
                    $data = array();
                    $read = sqimap_fgets($imap_stream);
                    break;
                }
                // end case substr($tag, 0, 1)
            // end case substr($tag, 0, 1)
            case '*':
                if (preg_match('/^\\*\\s\\d+\\sFETCH/', $read)) {
                    /* check for literal */
                    $s = substr($read, -3);
                    $fetch_data = array();
                    do {
                        /* outer loop, continue until next untagged fetch
                           or tagged reponse */
                        do {
                            /* innerloop for fetching literals. with this loop
                               we prohibid that literal responses appear in the
                               outer loop so we can trust the untagged and
                               tagged info provided by $read */
                            if ($s === "}\r\n") {
                                $j = strrpos($read, '{');
                                $iLit = substr($read, $j + 1, -3);
                                $fetch_data[] = $read;
                                $sLiteral = sqimap_fread($imap_stream, $iLit, $filter, $outputstream, $no_return);
                                if ($sLiteral === false) {
                                    /* error */
                                    break 4;
                                    /* while while switch while */
                                }
                                /* backwards compattibility */
                                $aLiteral = explode("\n", $sLiteral);
                                /* release not neaded data */
                                unset($sLiteral);
                                foreach ($aLiteral as $line) {
                                    $fetch_data[] = $line . "\n";
                                }
                                /* release not neaded data */
                                unset($aLiteral);
                                /* next fgets belongs to this fetch because
                                   we just got the exact literalsize and there
                                   must follow data to complete the response */
                                $read = sqimap_fgets($imap_stream);
                                if ($read === false) {
                                    /* error */
                                    break 4;
                                    /* while while switch while */
                                }
                                $fetch_data[] = $read;
                            } else {
                                $fetch_data[] = $read;
                            }
                            /* retrieve next line and check in the while
                               statements if it belongs to this fetch response */
                            $read = sqimap_fgets($imap_stream);
                            if ($read === false) {
                                /* error */
                                break 4;
                                /* while while switch while */
                            }
                            /* check for next untagged reponse and break */
                            if (substr($read, 0, 1) == '*') {
                                break 2;
                            }
                            $s = substr($read, -3);
                        } while ($s === "}\r\n");
                        $s = substr($read, -3);
                    } while (substr($read, 0, 1) !== '*' && substr($read, 0, strlen($tag)) !== $tag);
                    $resultlist[] = $fetch_data;
                    /* release not neaded data */
                    unset($fetch_data);
                } else {
                    $s = substr($read, -3);
                    do {
                        if ($s === "}\r\n") {
                            $j = strrpos($read, '{');
                            $iLit = substr($read, $j + 1, -3);
                            $data[] = $read;
                            $sLiteral = fread($imap_stream, $iLit);
                            if ($sLiteral === false) {
                                /* error */
                                $read = false;
                                break 3;
                                /* while switch while */
                            }
                            $data[] = $sLiteral;
                            $data[] = sqimap_fgets($imap_stream);
                        } else {
                            $data[] = $read;
                        }
                        $read = sqimap_fgets($imap_stream);
                        if ($read === false) {
                            break 3;
                            /* while switch while */
                        } elseif (substr($read, 0, 1) == '*') {
                            break;
                        }
                        $s = substr($read, -3);
                    } while ($s === "}\r\n");
                    break 1;
                }
                break;
                // end case '*'
        }
        // end switch
    }
    // end while
    /* error processing in case $read is false */
    if ($read === false) {
        unset($data);
        echo date("d.m.Y @ G:i:s") . ": ERROR: Connection dropped by IMAP server.\n";
        exit;
    }
    /* Set $resultlist array */
    if (!empty($data)) {
        $resultlist[] = $data;
    } elseif (empty($resultlist)) {
        $resultlist[] = array();
    }
    /* Return result or handle errors */
    if ($handle_errors == false) {
        return $resultlist;
    }
    switch ($response) {
        case 'OK':
            return $resultlist;
            break;
        case 'NO':
            /* ignore this error from M$ exchange, it is not fatal (aka bug) */
            if (strstr($message, 'command resulted in') === false) {
                echo date("d.m.Y @ G:i:s") . ": ERROR: Could not complete request.\n";
                exit;
            }
            break;
        case 'BAD':
            echo date("d.m.Y @ G:i:s") . ": ERROR: Bad or malformed request.\n";
            exit;
        case 'BYE':
            echo date("d.m.Y @ G:i:s") . ": ERROR: IMAP server closed the connection.\n";
            exit;
        default:
            echo date("d.m.Y @ G:i:s") . ": ERROR: Unknown IMAP response.\n";
            return $resultlist;
            break;
    }
}