1: <?php
2: /**
3: * Envelope data as returned by the IMAP FETCH command (RFC 3501 [7.4.2]).
4: *
5: * Copyright 2011-2012 Horde LLC (http://www.horde.org/)
6: *
7: * See the enclosed file COPYING for license information (LGPL). If you
8: * did not receive this file, see http://www.horde.org/licenses/lgpl21.
9: *
10: * @author Michael Slusarz <slusarz@horde.org>
11: * @category Horde
12: * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
13: * @package Imap_Client
14: *
15: * @property array $bcc Bcc address(es).
16: * @property array $bcc_decoded Bcc address(es) (MIME decoded).
17: * (Since 1.1.0)
18: * @property array $bcc_group Bcc address(es) with group
19: * objects. (Since 1.5.0)
20: * @property array $cc Cc address(es).
21: * @property array $cc_decoded Cc address(es) (MIME decoded).
22: * (Since 1.1.0)
23: * @property array $cc_group Cc address(es) with group
24: * objects. (Since 1.5.0)
25: * @property Horde_Imap_Client_DateTime $date IMAP internal date.
26: * @property array $from From address(es).
27: * @property array $from_decoded From address(es) (MIME decoded).
28: * (Since 1.1.0)
29: * @property string $in_reply_to Message-ID of the message
30: * replied to.
31: * @property string $message_id Message-ID of the message.
32: * @property array $reply_to Reply-to address(es).
33: * @property array $reply_to_decoded Reply-to address(es) (MIME
34: * decoded). (Since 1.1.0)
35: * @property array $sender Sender address.
36: * @property array $sender_decoded Sender address (MIME decoded).
37: * (Since 1.1.0)
38: * @property string $subject Subject.
39: * @property string $subject_decoded Subject (MIME decoded).
40: * (Since 1.1.0)
41: * @property array $to To address(es).
42: * @property array $to_decoded To address(es) (MIME decoded).
43: * (Since 1.1.0)
44: * @property array $to_group To address(es) with group
45: * objects. (Since 1.5.0)
46: *
47: * For array (address) properties, the values will be
48: * Horde_Mail_Rfc822_Address objects (since 1.4.4; the object is fully BC
49: * with the former array return).
50: */
51: class Horde_Imap_Client_Data_Envelope implements Serializable
52: {
53: /**
54: * Internal data array.
55: *
56: * @var array
57: */
58: protected $_data = array();
59:
60: /**
61: * Constructor.
62: *
63: * @var array $data An array of property names (keys) and values to set
64: * in this object.
65: */
66: public function __construct(array $data = array())
67: {
68: foreach ($data as $key => $val) {
69: $this->$key = $val;
70: }
71: }
72:
73: /**
74: */
75: public function __get($name)
76: {
77: if (isset($this->_data[$name])) {
78: switch ($name) {
79: case 'bcc':
80: case 'cc':
81: case 'to':
82: // These entries may have group data.
83: $out = array();
84: foreach ($this->_data[$name] as $val) {
85: if ($val instanceof Horde_Mail_Rfc822_Group) {
86: foreach ($val->addresses as $val2) {
87: $out[] = clone $val2;
88: }
89: } else {
90: $out[] = clone $val;
91: }
92: }
93: return $out;
94:
95: default:
96: return is_object($this->_data[$name])
97: ? clone $this->_data[$name]
98: : $this->_data[$name];
99: }
100: }
101:
102: switch ($name) {
103: case 'reply_to':
104: case 'sender':
105: if ($data = $this->from) {
106: return $data;
107: }
108: // Fall-through
109:
110: case 'bcc':
111: case 'cc':
112: case 'from':
113: case 'to':
114: return array();
115:
116: case 'date':
117: return new Horde_Imap_Client_DateTime();
118:
119: case 'subject_decoded':
120: return Horde_Mime::decode($this->subject, 'UTF-8');
121:
122: case 'bcc_decoded':
123: case 'cc_decoded':
124: case 'from_decoded':
125: case 'reply_to_decoded':
126: case 'sender_decoded':
127: case 'to_decoded':
128: $tmp = $this->__get(substr($name, 0, strrpos($name, '_')));
129: // Groups have already been trimmed.
130: foreach ($tmp as $val) {
131: $tmp->personal = $tmp->personal_decode;
132: }
133: return $tmp;
134:
135: case 'bcc_group':
136: case 'cc_group':
137: case 'to_group':
138: $entry = substr($name, 0, strpos($name, '_'));
139: if (!isset($this->_data[$entry])) {
140: return array();
141: }
142:
143: $tmp = clone $this->_data[$entry];
144: foreach ($tmp as $val) {
145: if ($val instanceof Horde_Mail_Rfc822_Group) {
146: foreach ($val->addresses as $val2) {
147: $val2->personal = $val2->personal_decode;
148: }
149: } else {
150: $val->personal = $val->personal_decode;
151: }
152: }
153: return $tmp;
154:
155: case 'in_reply_to':
156: case 'message_id':
157: case 'subject':
158: return '';
159: }
160:
161: return null;
162: }
163:
164: /**
165: */
166: public function __set($name, $value)
167: {
168: switch ($name) {
169: case 'bcc':
170: case 'cc':
171: case 'from':
172: case 'reply_to':
173: case 'sender':
174: case 'to':
175: switch ($name) {
176: case 'from':
177: foreach (array('reply_to', 'sender') as $val) {
178: if ($value == $this->$val) {
179: unset($this->_data[$val]);
180: }
181: }
182: break;
183:
184: case 'reply_to':
185: case 'sender':
186: if ($value == $this->from) {
187: unset($this->_data[$name]);
188: $value = array();
189: }
190: break;
191: }
192:
193: if (!empty($value)) {
194: $this->_data[$name] = array();
195: foreach ($value as $val) {
196: $val->personal = Horde_Mime_Headers::sanityCheck($name, $val->personal);
197: $this->_data[$name][] = $val;
198: }
199: }
200: break;
201:
202: case 'date':
203: $this->_data['date'] = new Horde_Imap_Client_DateTime($value);
204: break;
205:
206: case 'in_reply_to':
207: case 'message_id':
208: if (strlen($value)) {
209: $this->_data[$name] = $value;
210: }
211: break;
212:
213: case 'subject':
214: if (strlen($value)) {
215: $this->_data[$name] = Horde_Mime_Headers::sanityCheck($name, $value, array(
216: 'encode' => true
217: ));
218: }
219: break;
220: }
221: }
222:
223: /**
224: */
225: public function __isset($name)
226: {
227: switch ($name) {
228: case 'reply_to':
229: case 'sender':
230: return (isset($this->_data[$name]) ||
231: isset($this->_data['from']));
232: }
233:
234: return isset($this->_data[$name]);
235: }
236:
237: /* Serializable methods. */
238:
239: /**
240: */
241: public function serialize()
242: {
243: // For 1st serialzable version, we can rely on storage format change
244: // instead of explicit VERSION number.
245: return serialize(array(
246: 'd' => $this->_data
247: ));
248: }
249:
250: /**
251: */
252: public function unserialize($data)
253: {
254: $data = @unserialize($data);
255: if (!is_array($data) || !isset($data['d'])) {
256: throw new Exception('Cache version change');
257: }
258:
259: $this->_data = $data['d'];
260: }
261:
262: }
263: