1<?php
2/**
3 * Copyright 2014-2017 Horde LLC (http://www.horde.org/)
4 *
5 * See the enclosed file COPYING for license information (LGPL). If you
6 * did not receive this file, see http://www.horde.org/licenses/lgpl21.
7 *
8 * @category  Horde
9 * @copyright 2014-2017 Horde LLC
10 * @license   http://www.horde.org/licenses/lgpl21 LGPL 2.1
11 * @package   Imap_Client
12 */
13
14/**
15 * Query the capabilities of an IMAP server.
16 *
17 * @author    Michael Slusarz <slusarz@horde.org>
18 * @category  Horde
19 * @copyright 2014-2017 Horde LLC
20 * @license   http://www.horde.org/licenses/lgpl21 LGPL 2.1
21 * @package   Imap_Client
22 * @since     2.24.0
23 *
24 * @property-read integer $cmdlength  Allowable command length (in octets).
25 */
26class Horde_Imap_Client_Data_Capability_Imap
27extends Horde_Imap_Client_Data_Capability
28{
29    /**
30     * The list of enabled extensions.
31     *
32     * @var array
33     */
34    protected $_enabled = array();
35
36    /**
37     */
38    public function __get($name)
39    {
40        switch ($name) {
41        case 'cmdlength':
42            /* RFC 2683 [3.2.1.5] originally recommended that lines should
43             * be limited to "approximately 1000 octets". However, servers
44             * should allow a command line of at least "8000 octets".
45             * RFC 7162 [4] updates the recommendation to 8192 octets.
46             * As a compromise, assume all modern IMAP servers handle
47             * ~2000 octets and, if CONDSTORE/QRESYNC is supported, assume
48             * they can handle ~8000 octets. (Don't need dependency support
49             * checks here - the simple presence of CONDSTORE/QRESYNC is
50             * enough to trigger.) */
51             return (isset($this->_data['CONDSTORE']) || isset($this->_data['QRESYNC']))
52                 ? 8000
53                 : 2000;
54        }
55    }
56
57    /**
58     */
59    public function query($capability, $parameter = null)
60    {
61        if (parent::query($capability, $parameter)) {
62            return true;
63        }
64
65        switch (Horde_String::upper($capability)) {
66        case 'CONDSTORE':
67        case 'ENABLE':
68            /* RFC 7162 [3.2.3] - QRESYNC implies CONDSTORE and ENABLE. */
69            return (is_null($parameter) && $this->query('QRESYNC'));
70
71        case 'UTF8':
72            /* RFC 6855 [3] - UTF8=ONLY implies UTF8=ACCEPT. */
73            return ((Horde_String::upper($parameter) === 'ACCEPT') &&
74                    $this->query('UTF8', 'ONLY'));
75        }
76
77        return false;
78    }
79
80    /**
81     */
82    public function isEnabled($capability = null)
83    {
84        return is_null($capability)
85            ? $this->_enabled
86            : in_array(Horde_String::upper($capability), $this->_enabled);
87    }
88
89    /**
90     * Set a capability as enabled/disabled.
91     *
92     * @param array $capability  A capability (+ parameter).
93     * @param boolean $enable    If true, enables the capability.
94     */
95    public function enable($capability, $enable = true)
96    {
97        $capability = Horde_String::upper($capability);
98        $enabled = $this->isEnabled($capability);
99
100        if ($enable && !$enabled) {
101            switch ($capability) {
102            case 'QRESYNC':
103                /* RFC 7162 [3.2.3] - Enabling QRESYNC also implies enabling
104                 * of CONDSTORE. */
105                $this->enable('CONDSTORE');
106                break;
107            }
108
109            $this->_enabled[] = $capability;
110            $this->notify();
111        } elseif (!$enable && $enabled) {
112            $this->_enabled = array_diff($this->_enabled, array($capability));
113            $this->notify();
114        }
115    }
116
117}
118