1<?php
2/**
3 * Copyright 2011-2017 Horde LLC (http://www.horde.org/)
4 *
5 * See the enclosed file LICENSE 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 2011-2017 Horde LLC
10 * @license   http://www.horde.org/licenses/lgpl21 LGPL 2.1
11 * @package   Imap_Client
12 */
13
14/**
15 * Envelope data as returned by the IMAP FETCH command (RFC 3501 [7.4.2]).
16 *
17 * @author    Michael Slusarz <slusarz@horde.org>
18 * @category  Horde
19 * @copyright 2011-2017 Horde LLC
20 * @license   http://www.horde.org/licenses/lgpl21 LGPL 2.1
21 * @package   Imap_Client
22 *
23 * @todo $date should return null if it doesn't exist.
24 *
25 * @property Horde_Mail_Rfc822_List $bcc  Bcc address(es).
26 * @property Horde_Mail_Rfc822_List $cc  Cc address(es).
27 * @property Horde_Imap_Client_DateTime $date  Message date.
28 * @property Horde_Mail_Rfc822_List $from  From address(es).
29 * @property string $in_reply_to  Message-ID of the message replied to.
30 * @property string $message_id  Message-ID of the message.
31 * @property Horde_Mail_Rfc822_List $reply_to  Reply-to address(es).
32 * @property Horde_Mail_Rfc822_List $sender  Sender address.
33 * @property string $subject  Subject.
34 * @property Horde_Mail_Rfc822_List $to  To address(es).
35 */
36class Horde_Imap_Client_Data_Envelope implements Serializable
37{
38    /* Serializable version. */
39    const VERSION = 3;
40
41    /**
42     * Data object.
43     *
44     * @var Horde_Mime_Headers
45     */
46    protected $_data;
47
48    /**
49     * Constructor.
50     *
51     * @var array $data  An array of property names (keys) and values to set
52     *                   in this object.
53     */
54    public function __construct(array $data = array())
55    {
56        $this->_data = new Horde_Mime_Headers();
57
58        foreach ($data as $key => $val) {
59            $this->$key = $val;
60        }
61    }
62
63    /**
64     */
65    public function __get($name)
66    {
67        $name = $this->_normalizeProperty($name);
68
69        switch ($name) {
70        case 'bcc':
71        case 'cc':
72        case 'from':
73        case 'reply-to':
74        case 'sender':
75        case 'to':
76            if ($h = $this->_data[$name]) {
77                return $h->getAddressList(true);
78            }
79
80            if (in_array($name, array('sender', 'reply-to'))) {
81                return $this->from;
82            }
83            break;
84
85        case 'date':
86            if ($val = $this->_data['date']) {
87                return new Horde_Imap_Client_DateTime($val->value);
88            }
89            break;
90
91        case 'in-reply-to':
92        case 'message-id':
93        case 'subject':
94            if ($val = $this->_data[$name]) {
95                return $val->value;
96            }
97            break;
98        }
99
100        // Default values.
101        switch ($name) {
102        case 'bcc':
103        case 'cc':
104        case 'from':
105        case 'to':
106            return new Horde_Mail_Rfc822_List();
107
108        case 'date':
109            return new Horde_Imap_Client_DateTime();
110
111        case 'in-reply-to':
112        case 'message-id':
113        case 'subject':
114            return '';
115        }
116
117        return null;
118    }
119
120    /**
121     */
122    public function __set($name, $value)
123    {
124        if (!strlen($value)) {
125            return;
126        }
127
128        $name = $this->_normalizeProperty($name);
129
130        switch ($name) {
131        case 'bcc':
132        case 'cc':
133        case 'date':
134        case 'from':
135        case 'in-reply-to':
136        case 'message-id':
137        case 'reply-to':
138        case 'sender':
139        case 'subject':
140        case 'to':
141            switch ($name) {
142            case 'from':
143                if ($this->reply_to->match($value)) {
144                    unset($this->_data['reply-to']);
145                }
146                if ($this->sender->match($value)) {
147                    unset($this->_data['sender']);
148                }
149                break;
150
151            case 'reply-to':
152            case 'sender':
153                if ($this->from->match($value)) {
154                    unset($this->_data[$name]);
155                    return;
156                }
157                break;
158            }
159
160            $this->_data->addHeader($name, $value);
161            break;
162        }
163    }
164
165    /**
166     */
167    public function __isset($name)
168    {
169        $name = $this->_normalizeProperty($name);
170
171        switch ($name) {
172        case 'reply-to':
173        case 'sender':
174            if (isset($this->_data[$name])) {
175                return true;
176            }
177            $name = 'from';
178            break;
179        }
180
181        return isset($this->_data[$name]);
182    }
183
184    /**
185     */
186    protected function _normalizeProperty($name)
187    {
188        switch ($name) {
189        case 'in_reply_to':
190            return 'in-reply-to';
191
192        case 'message_id':
193            return 'message-id';
194
195        case 'reply_to':
196            return 'reply-to';
197        }
198
199        return $name;
200    }
201
202    /* Serializable methods. */
203
204    /**
205     */
206    public function serialize()
207    {
208        return serialize(array(
209            'd' => $this->_data,
210            'v' => self::VERSION
211        ));
212    }
213
214    /**
215     */
216    public function unserialize($data)
217    {
218        $data = @unserialize($data);
219        if (empty($data['v']) || ($data['v'] != self::VERSION)) {
220            throw new Exception('Cache version change');
221        }
222
223        $this->_data = $data['d'];
224    }
225
226}
227