/** * 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::r("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::r("Bad tagged response.")); } }
/** * Read data from incoming POP3 stream. * * @param integer $size UNUSED: The number of bytes to read from the * socket. * * @return string Line of data. * * @throws Horde_Imap_Client_Exception */ public function read($size = null) { if (feof($this->_stream)) { $this->close(); $this->_params['debug']->info('ERROR: Server closed the connection.'); throw new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::r("Server closed the connection unexpectedly."), Horde_Imap_Client_Exception::DISCONNECT); } if (($read = fgets($this->_stream)) === false) { $this->_params['debug']->info('ERROR: read/timeout error.'); throw new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::r("Error when communicating with the mail server."), Horde_Imap_Client_Exception::SERVER_READERROR); } $this->_params['debug']->server(rtrim($read, "\r\n")); return $read; }
/** * Gets a line from the stream and parses it. * * @param mixed $multiline 'array', 'none', 'stream', or null. * * @return array An array with the following keys: * - data: (mixed) Stream, array, or null. * - resp: (string) The server response text. * * @throws Horde_Imap_Client_Exception */ protected function _getResponse($multiline = false) { $ob = array('resp' => ''); $read = explode(' ', rtrim($this->_connection->read(), "\r\n"), 2); if (!in_array($read[0], array('+OK', '-ERR', '+'))) { $this->_debug->info('ERROR: IMAP read/timeout error.'); throw new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::r("Error when communicating with the mail server."), Horde_Imap_Client_Exception::SERVER_READERROR); } $respcode = null; if (isset($read[1]) && isset($this->_init['capability']) && $this->_capability('RESP-CODES')) { $respcode = $this->_parseResponseCode($read[1]); } switch ($read[0]) { case '+OK': case '+': if ($respcode) { $ob['resp'] = $respcode->text; } elseif (isset($read[1])) { $ob['resp'] = $read[1]; } break; case '-ERR': $errcode = 0; if ($respcode) { $errtext = $respcode->text; if (isset($respcode->code)) { switch ($respcode->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; // RFC 6856 [5] // RFC 6856 [5] case 'UTF8': /* This code can only be issued if we (as client) are * broken, so no need to handle since we should never * be broken. */ break; } } } elseif (isset($read[1])) { $errtext = $read[1]; } else { $errtext = '[No error message provided by server]'; } $e = new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::r("POP3 error reported by server."), $errcode); $e->details = $errtext; throw $e; } switch ($multiline) { case 'array': $ob['data'] = array(); break; case 'none': $ob['data'] = null; break; case 'stream': $ob['data'] = fopen('php://temp', 'r+'); break; default: return $ob; } do { $orig_read = $this->_connection->read(); $read = rtrim($orig_read, "\r\n"); if ($read === '.') { break; } elseif (substr($read, 0, 2) === '..') { $read = substr($read, 1); } if (is_array($ob['data'])) { $ob['data'][] = $read; } elseif (!is_null($ob['data'])) { fwrite($ob['data'], $orig_read); } } while (true); return $ob; }
/** * Handle status responses (see RFC 3501 [7.1]). * * @param Horde_Imap_Client_Interaction_Pipeline $pipeline Pipeline * object. * @param Horde_Imap_Client_Interaction_Server $ob Server object. * * @throws Horde_Imap_Client_Exception_ServerResponse */ protected function _responseCode(Horde_Imap_Client_Interaction_Pipeline $pipeline, 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::r("Charset used in search query is not supported on the mail server."), Horde_Imap_Client_Exception::BADCHARSET, $ob, $pipeline); case 'CAPABILITY': $this->_parseCapability($pipeline, $rc->data); break; case 'PARSE': /* Only throw error on NO/BAD. Message is human readable. */ switch ($ob->status) { case Horde_Imap_Client_Interaction_Server::BAD: case Horde_Imap_Client_Interaction_Server::NO: throw new Horde_Imap_Client_Exception_ServerResponse(sprintf(Horde_Imap_Client_Translation::r("The mail server was unable to parse the contents of the mail message: %s"), strval($ob->token)), Horde_Imap_Client_Exception::PARSEERROR, $ob, $pipeline); } break; 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] $pipeline->data['trycreate'] = true; break; case 'PERMANENTFLAGS': $this->_mailboxOb()->setStatus(Horde_Imap_Client::STATUS_PERMFLAGS, array_map('strtolower', $rc->data[0])); break; case 'UIDNEXT': $this->_mailboxOb()->setStatus(Horde_Imap_Client::STATUS_UIDNEXT, $rc->data[0]); break; case 'UIDVALIDITY': $this->_mailboxOb()->setStatus(Horde_Imap_Client::STATUS_UIDVALIDITY, $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->_mailboxOb()->setStatus(Horde_Imap_Client::STATUS_FIRSTUNSEEN, $rc->data[0]); break; case 'REFERRAL': // Defined by RFC 2221 $pipeline->data['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::r("The mail server was unable to parse the contents of the mail message."), Horde_Imap_Client_Exception::UNKNOWNCTE, $ob, $pipeline); case 'APPENDUID': // Defined by RFC 4315 // APPENDUID: [0] = UIDVALIDITY, [1] = UID(s) $pipeline->data['appenduid'] = $this->getIdsOb($rc->data[1]); break; case 'COPYUID': // Defined by RFC 4315 // COPYUID: [0] = UIDVALIDITY, [1] = UIDFROM, [2] = UIDTO $pipeline->data['copyuid'] = array_combine($this->getIdsOb($rc->data[1])->ids, $this->getIdsOb($rc->data[2])->ids); /* Use UIDPLUS information to move cached data to new mailbox (see * RFC 4549 [4.2.2.1]). Need to move now, because a MOVE might * EXPUNGE immediately afterwards. */ $this->_moveCache($pipeline->data['copydest'], $pipeline->data['copyuid'], $rc->data[0]); break; case 'UIDNOTSTICKY': // Defined by RFC 4315 [3] $this->_mailboxOb()->setStatus(Horde_Imap_Client::STATUS_UIDNOTSTICKY, true); break; case 'BADURL': // Defined by RFC 4469 [4.1] throw new Horde_Imap_Client_Exception_ServerResponse(Horde_Imap_Client_Translation::r("Could not save message on server."), Horde_Imap_Client_Exception::CATENATE_BADURL, $ob, $pipeline); case 'TOOBIG': // Defined by RFC 4469 [4.2] throw new Horde_Imap_Client_Exception_ServerResponse(Horde_Imap_Client_Translation::r("Could not save message data because it is too large."), Horde_Imap_Client_Exception::CATENATE_TOOBIG, $ob, $pipeline); case 'HIGHESTMODSEQ': // Defined by RFC 7162 [3.1.2.1] $pipeline->data['modseqs'][] = $rc->data[0]; break; case 'NOMODSEQ': // Defined by RFC 7162 [3.1.2.2] $pipeline->data['modseqs'][] = 0; break; case 'MODIFIED': // Defined by RFC 7162 [3.1.3] $pipeline->data['modified']->add($rc->data[0]); break; case 'CLOSED': // Defined by RFC 7162 [3.2.11] if (isset($pipeline->data['qresyncmbox'])) { /* If there is any pending FETCH cache entries, flush them * now before changing mailboxes. */ $this->_updateCache($pipeline->fetch); $pipeline->fetch->clear(); $this->_changeSelected($pipeline->data['qresyncmbox'][0], $pipeline->data['qresyncmbox'][1]); unset($pipeline->data['qresyncmbox']); } break; case 'NOTSAVED': // Defined by RFC 5182 [2.5] $pipeline->data['searchnotsaved'] = true; break; case 'BADCOMPARATOR': // Defined by RFC 5255 [4.9] throw new Horde_Imap_Client_Exception_ServerResponse(Horde_Imap_Client_Translation::r("The comparison algorithm was not recognized by the server."), Horde_Imap_Client_Exception::BADCOMPARATOR, $ob, $pipeline); case 'METADATA': $md = $rc->data[0]; switch ($md[0]) { case 'LONGENTRIES': // Defined by RFC 5464 [4.2.1] $pipeline->data['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::r("The metadata item could not be saved because it is too large."), Horde_Imap_Client_Exception::METADATA_MAXSIZE, $ob, $pipeline); case 'NOPRIVATE': // Defined by RFC 5464 [4.3] throw new Horde_Imap_Client_Exception_ServerResponse(Horde_Imap_Client_Translation::r("The metadata item could not be saved because the server does not support private annotations."), Horde_Imap_Client_Exception::METADATA_NOPRIVATE, $ob, $pipeline); case 'TOOMANY': // Defined by RFC 5464 [4.3] throw new Horde_Imap_Client_Exception_ServerResponse(Horde_Imap_Client_Translation::r("The metadata item could not be saved because the maximum number of annotations has been exceeded."), Horde_Imap_Client_Exception::METADATA_TOOMANY, $ob, $pipeline); } break; case 'UNAVAILABLE': // Defined by RFC 5530 [3] $pipeline->data['loginerr'] = new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::r("Remote server is temporarily unavailable."), Horde_Imap_Client_Exception::LOGIN_UNAVAILABLE); break; case 'AUTHENTICATIONFAILED': // Defined by RFC 5530 [3] $pipeline->data['loginerr'] = new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::r("Authentication failed."), Horde_Imap_Client_Exception::LOGIN_AUTHENTICATIONFAILED); break; case 'AUTHORIZATIONFAILED': // Defined by RFC 5530 [3] $pipeline->data['loginerr'] = new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::r("Authentication was successful, but authorization failed."), Horde_Imap_Client_Exception::LOGIN_AUTHORIZATIONFAILED); break; case 'EXPIRED': // Defined by RFC 5530 [3] $pipeline->data['loginerr'] = new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::r("Authentication credentials have expired."), Horde_Imap_Client_Exception::LOGIN_EXPIRED); break; case 'PRIVACYREQUIRED': // Defined by RFC 5530 [3] $pipeline->data['loginerr'] = new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::r("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::r("You do not have adequate permissions to carry out this operation."), Horde_Imap_Client_Exception::NOPERM, $ob, $pipeline); case 'INUSE': // Defined by RFC 5530 [3] throw new Horde_Imap_Client_Exception_ServerResponse(Horde_Imap_Client_Translation::r("There was a temporary issue when attempting this operation. Please try again later."), Horde_Imap_Client_Exception::INUSE, $ob, $pipeline); case 'EXPUNGEISSUED': // Defined by RFC 5530 [3] $pipeline->data['expungeissued'] = true; break; case 'CORRUPTION': // Defined by RFC 5530 [3] throw new Horde_Imap_Client_Exception_ServerResponse(Horde_Imap_Client_Translation::r("The mail server is reporting corrupt data in your mailbox."), Horde_Imap_Client_Exception::CORRUPTION, $ob, $pipeline); case 'SERVERBUG': case 'CLIENTBUG': case 'CANNOT': // Defined by RFC 5530 [3] $this->_debug->info('ERROR: mail server explicitly reporting an error.'); break; case 'LIMIT': // Defined by RFC 5530 [3] throw new Horde_Imap_Client_Exception_ServerResponse(Horde_Imap_Client_Translation::r("The mail server has denied the request."), Horde_Imap_Client_Exception::LIMIT, $ob, $pipeline); case 'OVERQUOTA': // Defined by RFC 5530 [3] throw new Horde_Imap_Client_Exception_ServerResponse(Horde_Imap_Client_Translation::r("The operation failed because the quota has been exceeded on the mail server."), Horde_Imap_Client_Exception::OVERQUOTA, $ob, $pipeline); case 'ALREADYEXISTS': // Defined by RFC 5530 [3] throw new Horde_Imap_Client_Exception_ServerResponse(Horde_Imap_Client_Translation::r("The object could not be created because it already exists."), Horde_Imap_Client_Exception::ALREADYEXISTS, $ob, $pipeline); case 'NONEXISTENT': // Defined by RFC 5530 [3] throw new Horde_Imap_Client_Exception_ServerResponse(Horde_Imap_Client_Translation::r("The object could not be deleted because it does not exist."), Horde_Imap_Client_Exception::NONEXISTENT, $ob, $pipeline); case 'USEATTR': // Defined by RFC 6154 [3] throw new Horde_Imap_Client_Exception_ServerResponse(Horde_Imap_Client_Translation::r("The special-use attribute requested for the mailbox is not supported."), Horde_Imap_Client_Exception::USEATTR, $ob, $pipeline); case 'DOWNGRADED': // Defined by RFC 6858 [3] $downgraded = $this->getIdsOb($rc->data[0]); foreach ($pipeline->fetch as $val) { if (in_array($val->getUid(), $downgraded)) { $val->setDowngraded(true); } } break; case 'XPROXYREUSE': // The proxy connection was reused, so no need to do login tasks. $pipeline->data['proxyreuse'] = true; break; default: // Unknown response codes SHOULD be ignored - RFC 3501 [7.1] break; } }
/** * 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::r("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::r("Error converting UTF7-IMAP string."), Horde_Imap_Client_Exception::UTF7IMAP_CONVERSION); } if ($n > --$u8len) { throw new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::r("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::r("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::r("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; }
/** * Read data from incoming IMAP stream. * * @return Horde_Imap_Client_Tokenize The tokenized data. * * @throws Horde_Imap_Client_Exception */ public function read() { $got_data = false; $literal_len = null; $token = new Horde_Imap_Client_Tokenize(); do { if (feof($this->_stream)) { $this->close(); $this->_params['debug']->info('ERROR: Server closed the connection.'); throw new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::r("Mail server closed the connection unexpectedly."), Horde_Imap_Client_Exception::DISCONNECT); } if (is_null($literal_len)) { $buffer = ''; while (($in = fgets($this->_stream)) !== false) { $got_data = true; if (substr($in, -1) === "\n") { $in = rtrim($in); $this->_params['debug']->server($buffer . $in); $token->add($in); break; } $buffer .= $in; $token->add($in); } /* Check for literal data. */ if (is_null($len = $token->getLiteralLength())) { break; } // Skip 0-length literal data. if ($len['length']) { $binary = $len['binary']; $literal_len = $len['length']; } continue; } $old_len = $literal_len; while ($literal_len > 0 && !feof($this->_stream)) { $in = fread($this->_stream, min($literal_len, 8192)); $token->add($in); if (!empty($this->_params['debugliteral'])) { $this->_params['debug']->raw($in); } $got_data = true; $literal_len -= strlen($in); } $literal_len = null; if (empty($this->_params['debugliteral'])) { $this->_params['debug']->server('[' . ($binary ? 'BINARY' : 'LITERAL') . ' DATA: ' . $old_len . ' bytes]'); } } while (true); if (!$got_data) { $this->_params['debug']->info('ERROR: read/timeout error.'); throw new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::r("Error when communicating with the mail server."), Horde_Imap_Client_Exception::SERVER_READERROR); } return $token; }
/** * 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::r("Authentication failure."), Horde_Imap_Client_Exception::SERVER_CONNECT); } return $tokens; }
/** * Constructor. * * @param string $feature The feature not supported in POP3. */ public function __construct($feature) { parent::__construct(sprintf(Horde_Imap_Client_Translation::r("%s not supported on POP3 servers."), $feature), self::NOT_SUPPORTED); }
/** * Constructor. * * @param string $user Username. * @param string $pass Password. * @param string $hash Hash name. * * @throws Horde_Imap_Client_Exception */ public function __construct($user, $pass, $hash = 'SHA1') { $error = false; $this->_hash = $hash; try { if (!class_exists('Horde_Stringprep') || !class_exists('Horde_Crypt_Blowfish_Pbkdf2')) { throw new Exception(); } Horde_Stringprep::autoload(); $saslprep = new Znerol\Component\Stringprep\Profile\SASLprep(); $this->_user = $saslprep->apply($user, 'UTF-8', Znerol\Component\Stringprep\Profile::MODE_QUERY); $this->_pass = $saslprep->apply($pass, 'UTF-8', Znerol\Component\Stringprep\Profile::MODE_STORE); } catch (Znerol\Component\Stringprep\ProfileException $e) { $error = true; } catch (Exception $e) { $error = true; } if ($error) { throw new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::r("Authentication failure."), Horde_Imap_Client_Exception::LOGIN_AUTHORIZATIONFAILED); } /* Generate nonce. (Done here so this can be overwritten for * testing purposes.) */ $this->_nonce = strval(new Horde_Support_Randomid()); }
/** * Store message flag data (see RFC 3501 [6.4.6]). * * @param mixed $mailbox The mailbox containing the messages to modify. * Either a Horde_Imap_Client_Mailbox object or a * string (UTF-8). * @param array $options Additional options: * - add: (array) An array of flags to add. * DEFAULT: No flags added. * - ids: (Horde_Imap_Client_Ids) The list of messages to modify. * DEFAULT: All messages in $mailbox will be modified. * - remove: (array) An array of flags to remove. * DEFAULT: No flags removed. * - replace: (array) Replace the current flags with this set * of flags. Overrides both the 'add' and 'remove' options. * DEFAULT: No replace is performed. * - unchangedsince: (integer) Only changes flags if the mod-sequence ID * of the message is equal or less than this value. * Requires the CONDSTORE IMAP extension on the server. * Also requires the mailbox to support mod-sequences. * Will throw an exception if either condition is not * met. * DEFAULT: mod-sequence is ignored when applying * changes * * @return Horde_Imap_Client_Ids A Horde_Imap_Client_Ids object * containing the list of IDs that failed * the 'unchangedsince' test. * * @throws Horde_Imap_Client_Exception * @throws Horde_Imap_Client_Exception_NoSupportExtension */ public function store($mailbox, array $options = array()) { // Open mailbox call will handle the login. $this->openMailbox($mailbox, Horde_Imap_Client::OPEN_READWRITE); /* SEARCHRES requires server support. */ if (empty($options['ids'])) { $options['ids'] = $this->getIdsOb(Horde_Imap_Client_Ids::ALL); } elseif ($options['ids']->isEmpty()) { return $this->getIdsOb(); } elseif ($options['ids']->search_res && !$this->_capability('SEARCHRES')) { throw new Horde_Imap_Client_Exception_NoSupportExtension('SEARCHRES'); } if (!empty($options['unchangedsince'])) { if (!$this->_capability()->isEnabled('CONDSTORE')) { throw new Horde_Imap_Client_Exception_NoSupportExtension('CONDSTORE'); } /* RFC 7162 [3.1.2.2] - trying to do a UNCHANGEDSINCE STORE on a * mailbox that doesn't support it will return BAD. */ if (!$this->_mailboxOb()->getStatus(Horde_Imap_Client::STATUS_HIGHESTMODSEQ)) { throw new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::r("Mailbox does not support mod-sequences."), Horde_Imap_Client_Exception::MBOXNOMODSEQ); } } return $this->_store($options); }
/** * Constructor. * * @param string $feature The feature not supported in POP3. */ public function __construct($feature) { parent::__construct(Horde_Imap_Client_Translation::r("%s not supported on POP3 servers."), self::NOT_SUPPORTED); $this->messagePrintf(array($feature)); }
/** * 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::r("Cannot convert search query text to new charset"), self::BADCHARSET); }