Horde_Imap_Client_Socket::_append PHP Method

_append() protected method

protected _append ( Horde_Imap_Client_Mailbox $mailbox, $data, $options )
$mailbox Horde_Imap_Client_Mailbox
    protected function _append(Horde_Imap_Client_Mailbox $mailbox, $data, $options)
    {
        $c = $this->_capability();
        // Check for MULTIAPPEND extension (RFC 3502)
        if (count($data) > 1 && !$c->query('MULTIAPPEND')) {
            $result = $this->getIdsOb();
            foreach (array_keys($data) as $key) {
                $res = $this->_append($mailbox, array($data[$key]), $options);
                if ($res === true || $result === true) {
                    $result = true;
                } else {
                    $result->add($res);
                }
            }
            return $result;
        }
        // Check for extensions.
        $binary = $c->query('BINARY');
        $catenate = $c->query('CATENATE');
        $utf8 = $c->isEnabled('UTF8=ACCEPT');
        $asize = 0;
        $cmd = $this->_command('APPEND')->add($this->_getMboxFormatOb($mailbox));
        $cmd->literal8 = true;
        foreach (array_keys($data) as $key) {
            if (!empty($data[$key]['flags'])) {
                $tmp = new Horde_Imap_Client_Data_Format_List();
                foreach ($data[$key]['flags'] as $val) {
                    /* Ignore recent flag. RFC 3501 [9]: flag definition */
                    if (strcasecmp($val, Horde_Imap_Client::FLAG_RECENT) !== 0) {
                        $tmp->add($val);
                    }
                }
                $cmd->add($tmp);
            }
            if (!empty($data[$key]['internaldate'])) {
                $cmd->add(new Horde_Imap_Client_Data_Format_DateTime($data[$key]['internaldate']));
            }
            $adata = null;
            if (is_array($data[$key]['data'])) {
                if ($catenate) {
                    $cmd->add('CATENATE');
                    $tmp = new Horde_Imap_Client_Data_Format_List();
                } else {
                    $data_stream = new Horde_Stream_Temp();
                }
                reset($data[$key]['data']);
                while (list(, $v) = each($data[$key]['data'])) {
                    switch ($v['t']) {
                        case 'text':
                            if ($catenate) {
                                $tdata = $this->_appendData($v['v'], $asize);
                                if ($utf8) {
                                    /* RFC 6855 [4]: CATENATE UTF8 extension. */
                                    $tdata->forceBinary();
                                    $tmp->add(array('UTF8', new Horde_Imap_Client_Data_Format_List($tdata)));
                                } else {
                                    $tmp->add(array('TEXT', $tdata));
                                }
                            } else {
                                if (is_resource($v['v'])) {
                                    rewind($v['v']);
                                }
                                $data_stream->add($v['v']);
                            }
                            break;
                        case 'url':
                            if ($catenate) {
                                $tmp->add(array('URL', new Horde_Imap_Client_Data_Format_Astring($v['v'])));
                            } else {
                                $data_stream->add($this->_convertCatenateUrl($v['v']));
                            }
                            break;
                    }
                }
                if ($catenate) {
                    $cmd->add($tmp);
                } else {
                    $adata = $this->_appendData($data_stream->stream, $asize);
                }
            } else {
                $adata = $this->_appendData($data[$key]['data'], $asize);
            }
            if (!is_null($adata)) {
                if ($utf8) {
                    /* RFC 6855 [4]: APPEND UTF8 extension. */
                    $adata->forceBinary();
                    $cmd->add(array('UTF8', new Horde_Imap_Client_Data_Format_List($adata)));
                } else {
                    $cmd->add($adata);
                }
            }
        }
        /* Although it is normally more efficient to use LITERAL+, disable if
         * payload is over 50 KB because it allows the server to throw error
         * before we potentially push a lot of data to server that would
         * otherwise be ignored (see RFC 4549 [4.2.2.3]).
         * Additionally, since so many IMAP servers have issues with APPEND
         * + BINARY, don't use LITERAL+ since servers may send BAD
         * (incorrectly) after initial command. */
        $cmd->literalplus = $asize < 1024 * 50 && !$binary;
        // If the mailbox is currently selected read-only, we need to close
        // because some IMAP implementations won't allow an append. And some
        // implementations don't support append on ANY open mailbox. Be safe
        // and always make sure we are in a non-selected state.
        $this->close();
        try {
            $resp = $this->_sendCmd($cmd);
        } catch (Horde_Imap_Client_Exception $e) {
            switch ($e->getCode()) {
                case $e::CATENATE_BADURL:
                case $e::CATENATE_TOOBIG:
                    /* Cyrus 2.4 (at least as of .14) has a broken CATENATE (see
                     * Bug #11111). Regardless, if CATENATE is broken, we can try
                     * to fallback to APPEND. */
                    $c->remove('CATENATE');
                    return $this->_append($mailbox, $data, $options);
                case $e::DISCONNECT:
                    /* Workaround broken literal8 on Cyrus. */
                    if ($binary) {
                        // Need to re-login first before removing capability.
                        $this->login();
                        $c->remove('BINARY');
                        return $this->_append($mailbox, $data, $options);
                    }
                    break;
            }
            if (!empty($options['create']) && !empty($e->resp_data['trycreate'])) {
                $this->createMailbox($mailbox);
                unset($options['create']);
                return $this->_append($mailbox, $data, $options);
            }
            /* RFC 3516/4466 says we should be able to append binary data
             * using literal8 "~{#} format", but it doesn't seem to work on
             * all servers tried (UW-IMAP/Cyrus). Do a last-ditch check for
             * broken BINARY and attempt to fix here. */
            if ($c->query('BINARY') && $e instanceof Horde_Imap_Client_Exception_ServerResponse) {
                switch ($e->status) {
                    case Horde_Imap_Client_Interaction_Server::BAD:
                    case Horde_Imap_Client_Interaction_Server::NO:
                        $c->remove('BINARY');
                        return $this->_append($mailbox, $data, $options);
                }
            }
            throw $e;
        }
        /* If we reach this point and have data in 'appenduid', UIDPLUS (RFC
         * 4315) has done the dirty work for us. */
        return isset($resp->data['appenduid']) ? $resp->data['appenduid'] : true;
    }