/** * Constructor. * * @param string $extension The extension not supported on the server. * @param string $msg A non-standard error message to use instead * of the default. */ public function __construct($extension, $msg = null) { $this->extension = $extension; if (is_null($msg)) { $msg = sprintf(Horde_Imap_Client_Translation::t("The server does not support the %s extension."), $extension); } parent::__construct($msg, self::NOT_SUPPORTED); }
/** * @param string $tag Response tag. */ public function __construct(Horde_Imap_Client_Tokenize $token, $tag) { $this->tag = $tag; parent::__construct($token); if (is_null($this->status)) { throw new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::t("Bad tagged response.")); } }
/** * Handle status responses (see RFC 3501 [7.1]). * * @param Horde_Imap_Client_Interaction_Server $ob Server object. * * @throws Horde_Imap_Client_Exception_ServerResponse */ protected function _responseCode(Horde_Imap_Client_Interaction_Server $ob) { if (is_null($ob->responseCode)) { return; } $rc = $ob->responseCode; switch ($rc->code) { case 'ALERT': // Defined by RFC 5530 [3] - Treat as an alert for now. // Defined by RFC 5530 [3] - Treat as an alert for now. case 'CONTACTADMIN': if (!isset($this->_temp['alerts'])) { $this->_temp['alerts'] = array(); } $this->_temp['alerts'][] = strval($ob->token); break; case 'BADCHARSET': /* Store valid search charsets if returned by server. */ $s_charset = array(); foreach ($rc->data[0] as $val) { $s_charset[$val] = true; } if (!empty($s_charset)) { $this->_setInit('s_charset', array_merge($this->_init['s_charset'], $s_charset)); } throw new Horde_Imap_Client_Exception_ServerResponse(Horde_Imap_Client_Translation::t("Charset used in search query is not supported on the mail server."), Horde_Imap_Client_Exception::BADCHARSET, $ob->status, strval($ob->token)); case 'CAPABILITY': $this->_parseCapability($rc->data); break; case 'PARSE': throw new Horde_Imap_Client_Exception_ServerResponse(Horde_Imap_Client_Translation::t("The mail server was unable to parse the contents of the mail message."), Horde_Imap_Client_Exception::PARSEERROR, $ob->status, strval($ob->token)); case 'READ-ONLY': $this->_mode = Horde_Imap_Client::OPEN_READONLY; break; case 'READ-WRITE': $this->_mode = Horde_Imap_Client::OPEN_READWRITE; break; case 'TRYCREATE': // RFC 3501 [7.1] $this->_temp['trycreate'] = true; break; case 'PERMANENTFLAGS': $this->_temp['mailbox']['permflags'] = array_map('strtolower', $rc->data[0]); break; case 'UIDNEXT': case 'UIDVALIDITY': $this->_temp['mailbox'][strtolower($rc->code)] = $rc->data[0]; break; case 'UNSEEN': /* This is different from the STATUS UNSEEN response - this item, * if defined, returns the first UNSEEN message in the mailbox. */ $this->_temp['mailbox']['firstunseen'] = $rc->data[0]; break; case 'REFERRAL': // Defined by RFC 2221 $this->_temp['referral'] = new Horde_Imap_Client_Url($rc->data[0]); break; case 'UNKNOWN-CTE': // Defined by RFC 3516 throw new Horde_Imap_Client_Exception_ServerResponse(Horde_Imap_Client_Translation::t("The mail server was unable to parse the contents of the mail message."), Horde_Imap_Client_Exception::UNKNOWNCTE, $ob->status, strval($ob->token)); case 'APPENDUID': case 'COPYUID': // Defined by RFC 4315 // APPENDUID: [0] = UIDVALIDITY, [1] = UID(s) // COPYUID: [0] = UIDVALIDITY, [1] = UIDFROM, [2] = UIDTO if ($this->_temp['uidplusmbox']->equals($this->_selected) && $this->_temp['mailbox']['uidvalidity'] != $rc->data[0]) { $this->_temp['mailbox'] = array('uidvalidity' => $rc->data[0]); $this->_temp['searchnotsaved'] = true; } /* Check for cache expiration (see RFC 4549 [4.1]). */ $this->_updateCache(new Horde_Imap_Client_Fetch_Results(), array('mailbox' => $this->_temp['uidplusmbox'], 'uidvalid' => $rc->data[0])); if ($rc->code == 'APPENDUID') { $this->_temp['appenduid']->add($rc->data[1]); } else { $from = $this->getIdsOb($rc->data[1]); $to = $this->getIdsOb($rc->data[2]); $this->_temp['copyuid'] = array_combine($from->ids, $to->ids); $this->_temp['copyuidvalid'] = $rc->data[0]; } break; case 'UIDNOTSTICKY': // Defined by RFC 4315 [3] $this->_temp['mailbox']['uidnotsticky'] = true; break; case 'BADURL': // Defined by RFC 4469 [4.1] throw new Horde_Imap_Client_Exception_ServerResponse(Horde_Imap_Client_Translation::t("Could not save message on server."), Horde_Imap_Client_Exception::CATENATE_BADURL, $ob->status, strval($ob->token)); case 'TOOBIG': // Defined by RFC 4469 [4.2] throw new Horde_Imap_Client_Exception_ServerResponse(Horde_Imap_Client_Translation::t("Could not save message data because it is too large."), Horde_Imap_Client_Exception::CATENATE_TOOBIG, $ob->status, strval($ob->token)); case 'HIGHESTMODSEQ': // Defined by RFC 4551 [3.1.1] $this->_temp['modseqs'][] = $rc->data[0]; break; case 'NOMODSEQ': // Defined by RFC 4551 [3.1.2] $this->_temp['modseqs'][] = 0; break; case 'MODIFIED': // Defined by RFC 4551 [3.2] $this->_temp['modified']->add($rc->data[0]); break; case 'CLOSED': // Defined by RFC 5162 [3.7] if (isset($this->_temp['qresyncmbox'])) { $this->_temp['mailbox'] = array('name' => $this->_temp['qresyncmbox']); $this->_selected = $this->_temp['qresyncmbox']; } break; case 'NOTSAVED': // Defined by RFC 5182 [2.5] $this->_temp['searchnotsaved'] = true; break; case 'BADCOMPARATOR': // Defined by RFC 5255 [4.9] throw new Horde_Imap_Client_Exception_ServerResponse(Horde_Imap_Client_Translation::t("The comparison algorithm was not recognized by the server."), Horde_Imap_Client_Exception::BADCOMPARATOR, $ob->status, strval($ob->token)); case 'METADATA': $md = $rc->data[0]; switch ($md[0]) { case 'LONGENTRIES': // Defined by RFC 5464 [4.2.1] $this->_temp['metadata']['*longentries'] = intval($md[1]); break; case 'MAXSIZE': // Defined by RFC 5464 [4.3] throw new Horde_Imap_Client_Exception_ServerResponse(Horde_Imap_Client_Translation::t("The metadata item could not be saved because it is too large."), Horde_Imap_Client_Exception::METADATA_MAXSIZE, $ob->status, intval($md[1])); case 'NOPRIVATE': // Defined by RFC 5464 [4.3] throw new Horde_Imap_Client_Exception_ServerResponse(Horde_Imap_Client_Translation::t("The metadata item could not be saved because the server does not support private annotations."), Horde_Imap_Client_Exception::METADATA_NOPRIVATE, $ob->status, strval($ob->token)); case 'TOOMANY': // Defined by RFC 5464 [4.3] throw new Horde_Imap_Client_Exception_ServerResponse(Horde_Imap_Client_Translation::t("The metadata item could not be saved because the maximum number of annotations has been exceeded."), Horde_Imap_Client_Exception::METADATA_TOOMANY, $ob->status, strval($ob->token)); } break; case 'UNAVAILABLE': // Defined by RFC 5530 [3] $this->_temp['loginerr'] = new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::t("Remote server is temporarily unavailable."), Horde_Imap_Client_Exception::LOGIN_UNAVAILABLE); break; case 'AUTHENTICATIONFAILED': // Defined by RFC 5530 [3] $this->_temp['loginerr'] = new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::t("Authentication failed."), Horde_Imap_Client_Exception::LOGIN_AUTHENTICATIONFAILED); break; case 'AUTHORIZATIONFAILED': // Defined by RFC 5530 [3] $this->_temp['loginerr'] = new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::t("Authentication was successful, but authorization failed."), Horde_Imap_Client_Exception::LOGIN_AUTHORIZATIONFAILED); break; case 'EXPIRED': // Defined by RFC 5530 [3] $this->_temp['loginerr'] = new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::t("Authentication credentials have expired."), Horde_Imap_Client_Exception::LOGIN_EXPIRED); break; case 'PRIVACYREQUIRED': // Defined by RFC 5530 [3] $this->_temp['loginerr'] = new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::t("Operation failed due to a lack of a secure connection."), Horde_Imap_Client_Exception::LOGIN_PRIVACYREQUIRED); break; case 'NOPERM': // Defined by RFC 5530 [3] throw new Horde_Imap_Client_Exception_ServerResponse(Horde_Imap_Client_Translation::t("You do not have adequate permissions to carry out this operation."), Horde_Imap_Client_Exception::NOPERM, $ob->status, strval($ob->token)); case 'INUSE': // Defined by RFC 5530 [3] throw new Horde_Imap_Client_Exception_ServerResponse(Horde_Imap_Client_Translation::t("There was a temporary issue when attempting this operation. Please try again later."), Horde_Imap_Client_Exception::INUSE, $ob->status, strval($ob->token)); case 'EXPUNGEISSUED': // Defined by RFC 5530 [3] $this->_temp['expungeissued'] = true; break; case 'CORRUPTION': // Defined by RFC 5530 [3] throw new Horde_Imap_Client_Exception_ServerResponse(Horde_Imap_Client_Translation::t("The mail server is reporting corrupt data in your mailbox."), Horde_Imap_Client_Exception::CORRUPTION, $ob->status, strval($ob->token)); case 'SERVERBUG': case 'CLIENTBUG': case 'CANNOT': // Defined by RFC 5530 [3] $this->writeDebug("ERROR: mail server explicitly reporting an error.\n", Horde_Imap_Client::DEBUG_INFO); break; case 'LIMIT': // Defined by RFC 5530 [3] throw new Horde_Imap_Client_Exception_ServerResponse(Horde_Imap_Client_Translation::t("The mail server has denied the request."), Horde_Imap_Client_Exception::LIMIT, $ob->status, strval($ob->token)); case 'OVERQUOTA': // Defined by RFC 5530 [3] throw new Horde_Imap_Client_Exception_ServerResponse(Horde_Imap_Client_Translation::t("The operation failed because the quota has been exceeded on the mail server."), Horde_Imap_Client_Exception::OVERQUOTA, $ob->status, strval($ob->token)); case 'ALREADYEXISTS': // Defined by RFC 5530 [3] throw new Horde_Imap_Client_Exception_ServerResponse(Horde_Imap_Client_Translation::t("The object could not be created because it already exists."), Horde_Imap_Client_Exception::ALREADYEXISTS, $ob->status, strval($ob->token)); case 'NONEXISTENT': // Defined by RFC 5530 [3] throw new Horde_Imap_Client_Exception_ServerResponse(Horde_Imap_Client_Translation::t("The object could not be deleted because it does not exist."), Horde_Imap_Client_Exception::NONEXISTENT, $ob->status, strval($ob->token)); case 'USEATTR': // Defined by RFC 6154 [3] throw new Horde_Imap_Client_Exception_ServerResponse(Horde_Imap_Client_Translation::t("The special-use attribute requested for the mailbox is not supported."), Horde_Imap_Client_Exception::USEATTR, $ob->status, strval($ob->token)); case 'XPROXYREUSE': // The proxy connection was reused, so no need to do login tasks. $this->_temp['proxyreuse'] = true; break; default: // Unknown response codes SHOULD be ignored - RFC 3501 [7.1] break; } }
/** * Gets a line from the stream and parses it. * * @return array An array with the following keys: * - line: (string) The server response text. * - response: (string) Either 'OK', 'END', '+', or ''. * * @throws Horde_Imap_Client_Exception */ protected function _getLine() { $ob = array('line' => '', 'response' => ''); if (feof($this->_stream)) { $this->logout(); throw new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::t("POP3 Server closed the connection unexpectedly."), Horde_Imap_Client_Exception::DISCONNECT); } $read = rtrim(fgets($this->_stream)); if (empty($read)) { return; } $this->writeDebug($read . "\n", Horde_Imap_Client::DEBUG_SERVER); $orig_read = $read; $read = explode(' ', $read, 2); switch ($read[0]) { case '+OK': $ob['response'] = 'OK'; if (isset($read[1]) && $this->queryCapability('RESP-CODES')) { $response = $this->_parseResponseCode($read[1]); $ob['line'] = $response->text; } break; case '-ERR': $errcode = 0; if (isset($read[1]) && $this->queryCapability('RESP-CODES')) { $response = $this->_parseResponseCode($read[1]); $errtext = $response->text; if (isset($response->code)) { switch ($response->code) { // RFC 2449 [8.1.1] case 'IN-USE': // RFC 2449 [8.1.2] // RFC 2449 [8.1.2] case 'LOGIN-DELAY': $errcode = Horde_Imap_Client_Exception::LOGIN_UNAVAILABLE; break; // RFC 3206 [4] // RFC 3206 [4] case 'SYS/TEMP': $errcode = Horde_Imap_Client_Exception::POP3_TEMP_ERROR; break; // RFC 3206 [4] // RFC 3206 [4] case 'SYS/PERM': $errcode = Horde_Imap_Client_Exception::POP3_PERM_ERROR; break; // RFC 3206 [5] // RFC 3206 [5] case 'AUTH': $errcode = Horde_Imap_Client_Exception::LOGIN_AUTHENTICATIONFAILED; break; } } } else { $errtext = '[No error message provided by server]'; } throw new Horde_Imap_Client_Exception_ServerResponse(Horde_Imap_Client_Translation::t("POP3 error reported by server."), $errcode, '-ERR', $errtext); case '.': $ob['response'] = 'END'; break; case '+': $ob['response'] = '+'; break; default: $ob['line'] = $orig_read; break; } return $ob; }
/** * Constructor. * * @param string $message Error message (non-translated). * @param code $code Error code. */ public function __construct($message = null, $code = null) { parent::__construct($message, $code); $this->raw_msg = $this->message; try { $this->message = Horde_Imap_Client_Translation::t($this->message); } catch (Horde_Translation_Exception $e) { } }
/** * Convert a string from UTF-8 to UTF7-IMAP. * * @param string $str The UTF-8 string. * @param boolean $force Assume $str is UTF-8 (no-autodetection)? If * false, attempts to auto-detect if string is * already in UTF7-IMAP. * * @return string The converted UTF7-IMAP string. * @throws Horde_Imap_Client_Exception */ public static function Utf8ToUtf7Imap($str, $force = true) { if ($str instanceof Horde_Imap_Client_Mailbox) { return $str->utf7imap; } $str = strval($str); /* No need to do conversion if all chars are in US-ASCII range or if * no ampersand is present. But will assume that an already encoded * ampersand means string is in UTF7-IMAP already. */ if (!$force && !preg_match('/[\\x80-\\xff]|&$|&(?![,+A-Za-z0-9]*-)/', $str)) { return $str; } /* Try mbstring, if available, which should be faster. Don't use the * IMAP utf7_* functions because they are known to be buggy. */ if (is_null(self::$_mbstring)) { self::$_mbstring = extension_loaded('mbstring'); } if (self::$_mbstring) { return @mb_convert_encoding($str, 'UTF7-IMAP', 'UTF-8'); } $u8len = strlen($str); $i = 0; $base64 = false; $p = ''; $ptr =& self::$_base64; while ($u8len) { $u8 = $str[$i]; $c = ord($u8); if ($c < 0x80) { $ch = $c; $n = 0; } elseif ($c < 0xc2) { throw new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::t("Error converting UTF7-IMAP string."), Horde_Imap_Client_Exception::UTF7IMAP_CONVERSION); } elseif ($c < 0xe0) { $ch = $c & 0x1f; $n = 1; } elseif ($c < 0xf0) { $ch = $c & 0xf; $n = 2; } elseif ($c < 0xf8) { $ch = $c & 0x7; $n = 3; } elseif ($c < 0xfc) { $ch = $c & 0x3; $n = 4; } elseif ($c < 0xfe) { $ch = $c & 0x1; $n = 5; } else { throw new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::t("Error converting UTF7-IMAP string."), Horde_Imap_Client_Exception::UTF7IMAP_CONVERSION); } if ($n > --$u8len) { throw new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::t("Error converting UTF7-IMAP string."), Horde_Imap_Client_Exception::UTF7IMAP_CONVERSION); } ++$i; for ($j = 0; $j < $n; ++$j) { $o = ord($str[$i + $j]); if (($o & 0xc0) != 0x80) { throw new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::t("Error converting UTF7-IMAP string."), Horde_Imap_Client_Exception::UTF7IMAP_CONVERSION); } $ch = $ch << 6 | $o & 0x3f; } if ($n > 1 && !($ch >> $n * 5 + 1)) { throw new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::t("Error converting UTF7-IMAP string."), Horde_Imap_Client_Exception::UTF7IMAP_CONVERSION); } $i += $n; $u8len -= $n; if ($ch < 0x20 || $ch >= 0x7f) { if (!$base64) { $p .= '&'; $base64 = true; $b = 0; $k = 10; } if ($ch & ~0xffff) { $ch = 0xfffe; } $p .= $ptr[$b | $ch >> $k]; $k -= 6; for (; $k >= 0; $k -= 6) { $p .= $ptr[$ch >> $k & 0x3f]; } $b = $ch << -$k & 0x3f; $k += 16; } else { if ($base64) { if ($k > 10) { $p .= $ptr[$b]; } $p .= '-'; $base64 = false; } $p .= chr($ch); if (chr($ch) == '&') { $p .= '-'; } } } if ($base64) { if ($k > 10) { $p .= $ptr[$b]; } $p .= '-'; } return $p; }
/** * Parses and verifies the digest challenge. * * @param string $challenge The digest challenge * * @return array The parsed challenge as an array with directives as keys. * * @throws Horde_Imap_Client_Exception */ protected function _parseChallenge($challenge) { $tokens = array('maxbuf' => 65536, 'realm' => ''); preg_match_all('/([a-z-]+)=("[^"]+(?<!\\\\)"|[^,]+)/i', $challenge, $matches, PREG_SET_ORDER); foreach ($matches as $val) { $tokens[$val[1]] = trim($val[2], '"'); } // Required directives. if (!isset($tokens['nonce']) || !isset($tokens['algorithm'])) { throw new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::t("Authentication failure."), 'SERVER_CONNECT'); } return $tokens; }
/** * Expunge deleted messages from the given mailbox. * * @param mixed $mailbox The mailbox to expunge. Either a * Horde_Imap_Client_Mailbox object or a string * (UTF-8). * @param array $options Additional options: * - ids: (Horde_Imap_Client_Ids) A list of messages to expunge, but * only if they are also flagged as deleted. * DEFAULT: All messages marked as deleted will be expunged. * - list: (boolean) If true, returns the list of expunged messages * (UIDs only). * DEFAULT: false * * @return Horde_Imap_Client_Ids If 'list' option is true, returns the * UID list of expunged messages. * * @throws Horde_Imap_Client_Exception */ public function expunge($mailbox, array $options = array()) { // Open mailbox call will handle the login. $this->openMailbox($mailbox, Horde_Imap_Client::OPEN_READWRITE); /* Don't expunge if the mailbox is readonly. */ if ($this->_mode == Horde_Imap_Client::OPEN_READONLY) { throw new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::t("Cannot expunge read-only mailbox."), Horde_Imap_Client_Exception::MAILBOX_READONLY); } if (empty($options['ids'])) { $options['ids'] = $this->getIdsOb(Horde_Imap_Client_Ids::ALL); } elseif ($options['ids']->isEmpty()) { return $this->getIdsOb(); } return $this->_expunge($options); }
/** * Constructor. * * @param string $charset The charset that was attempted to be converted * to. */ public function __construct($charset) { $this->charset = $charset; parent::__construct(Horde_Imap_Client_Translation::t("Cannot convert search query text to new charset"), self::BADCHARSET); }
/** * Constructor. * * @param string $msg Error message (non-translated). * @param code $code Error code. */ public function __construct($message = null, $code = null) { parent::__construct($message, $code); $this->raw_msg = $this->message; $this->message = Horde_Imap_Client_Translation::t($this->message); }
/** * Constructor. * * @param string $feature The feature not supported in POP3. */ public function __construct($feature) { parent::__construct(sprintf(Horde_Imap_Client_Translation::t("%s not supported on POP3 servers."), $feature), self::NOT_SUPPORTED); }