1<?php
2/**
3 * Copyright 2008-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 2008-2017 Horde LLC
10 * @license   http://www.horde.org/licenses/lgpl21 LGPL 2.1
11 * @package   Imap_Client
12 */
13
14/**
15 * Object representation of a a POP3 (RFC 2384) or IMAP (RFC 5092/5593) URL.
16 *
17 * @author     Michael Slusarz <slusarz@horde.org>
18 * @category   Horde
19 * @copyright  2008-2016 Horde LLC
20 * @deprecated Use Horde_Imap_Client_Url_Base instead
21 * @license    http://www.horde.org/licenses/lgpl21 LGPL 2.1
22 * @package    Imap_Client
23 *
24 * @property-read boolean $relative  Is this a relative URL?
25 */
26class Horde_Imap_Client_Url implements Serializable
27{
28    /**
29     * The authentication method to use.
30     *
31     * @var string
32     */
33    public $auth = null;
34
35    /**
36     * The remote server (not present for relative URLs).
37     *
38     * @var string
39     */
40    public $hostspec = null;
41
42    /**
43     * The IMAP mailbox.
44     *
45     * @todo Make this a Horde_Imap_Client_Mailbox object.
46     *
47     * @var string
48     */
49    public $mailbox = null;
50
51    /**
52     * A byte range for use with IMAP FETCH.
53     *
54     * @var string
55     */
56    public $partial = null;
57
58    /**
59     * The remote port (not present for relative URLs).
60     *
61     * @var integer
62     */
63    public $port = null;
64
65    /**
66     * The protocol type. Either 'imap' or 'pop' (not present for relative
67     * URLs).
68     *
69     * @var string
70     */
71    public $protocol = null;
72
73    /**
74     * A search query to be run with IMAP SEARCH.
75     *
76     * @var string
77     */
78    public $search = null;
79
80    /**
81     * A MIME part ID.
82     *
83     * @var string
84     */
85    public $section = null;
86
87    /**
88     * The username to use on the remote server.
89     *
90     * @var string
91     */
92    public $username = null;
93
94    /**
95     * The IMAP UID.
96     *
97     * @var string
98     */
99    public $uid = null;
100
101    /**
102     * The IMAP UIDVALIDITY for the given mailbox.
103     *
104     * @var integer
105     */
106    public $uidvalidity = null;
107
108    /**
109     * URLAUTH info (not parsed).
110     *
111     * @var string
112     */
113    public $urlauth = null;
114
115    /**
116     * Constructor.
117     *
118     * Absolute IMAP URLs takes one of the following forms:
119     *   - imap://<iserver>[/]
120     *   - imap://<iserver>/<enc-mailbox>[<uidvalidity>][?<enc-search>]
121     *   - imap://<iserver>/<enc-mailbox>[<uidvalidity>]<iuid>[<isection>][<ipartial>][<iurlauth>]
122     *
123     * POP URLs take one of the following forms:
124     *   - pop://<user>;auth=<auth>@<host>:<port>
125     *
126     * @param string $url  A URL string.
127     */
128    public function __construct($url = null)
129    {
130        if (!is_null($url)) {
131            $this->_parse($url);
132        }
133    }
134
135    /**
136     * Create a POP3 (RFC 2384) or IMAP (RFC 5092/5593) URL.
137     *
138     * @return string  A URL string.
139     */
140    public function __toString()
141    {
142        $url = '';
143
144        if (!is_null($this->protocol)) {
145            $url = $this->protocol . '://';
146
147            if (!is_null($this->username)) {
148                $url .= $this->username;
149                if (!is_null($this->auth)) {
150                    $url .= ';AUTH=' . $this->auth;
151                }
152                $url .= '@';
153            }
154
155            $url .= $this->hostspec;
156
157            if (!is_null($this->port)) {
158                switch ($this->protocol) {
159                case 'imap':
160                    if ($this->port != 143) {
161                        $url .= ':' . $this->port;
162                    }
163                    break;
164
165                case 'pop':
166                    if ($this->port != 110) {
167                        $url .= ':' . $this->port;
168                    }
169                    break;
170                }
171            }
172        }
173
174        $url .= '/';
175
176        if (is_null($this->protocol) || ($this->protocol == 'imap')) {
177            $url .= rawurlencode($this->mailbox);
178
179            if (!empty($this->uidvalidity)) {
180                $url .= ';UIDVALIDITY=' . $this->uidvalidity;
181            }
182
183            if (!is_null($this->search)) {
184                $url .= '?' . rawurlencode($this->search);
185            } else {
186                if (!is_null($this->uid)) {
187                    $url .= '/;UID=' . $this->uid;
188                }
189
190                if (!is_null($this->section)) {
191                    $url .= '/;SECTION=' . $this->section;
192                }
193
194                if (!is_null($this->partial)) {
195                    $url .= '/;PARTIAL=' . $this->partial;
196                }
197
198                if (!is_null($this->urlauth)) {
199                    $url .= '/;URLAUTH=' . $this->urlauth;
200                }
201            }
202        }
203
204        return $url;
205    }
206
207    /**
208     */
209    public function __get($name)
210    {
211        switch ($name) {
212        case 'relative':
213            return (is_null($this->hostspec) &&
214                is_null($this->port) &&
215                is_null($this->protocol));
216        }
217    }
218
219    /**
220     */
221    protected function _parse($url)
222    {
223        $data = parse_url(trim($url));
224
225        if (isset($data['scheme'])) {
226            $protocol = Horde_String::lower($data['scheme']);
227            if (!in_array($protocol, array('imap', 'pop'))) {
228                return;
229            }
230
231            if (isset($data['host'])) {
232                $this->hostspec = $data['host'];
233            }
234            $this->port = isset($data['port'])
235                ? $data['port']
236                : (($protocol === 'imap') ? 143 : 110);
237            $this->protocol = $protocol;
238        }
239
240        /* Check for username/auth information. */
241        if (isset($data['user'])) {
242            if (($pos = stripos($data['user'], ';AUTH=')) !== false) {
243                $auth = substr($data['user'], $pos + 6);
244                if ($auth !== '*') {
245                    $this->auth = $auth;
246                }
247                $data['user'] = substr($data['user'], 0, $pos);
248            }
249
250            if (strlen($data['user'])) {
251                $this->username = $data['user'];
252            }
253        }
254
255        /* IMAP-only information. */
256        if (is_null($this->protocol) || ($this->protocol == 'imap')) {
257            if (isset($data['path'])) {
258                $data['path'] = ltrim($data['path'], '/');
259                $parts = explode('/;', $data['path']);
260
261                $mbox = array_shift($parts);
262                if (($pos = stripos($mbox, ';UIDVALIDITY=')) !== false) {
263                    $this->uidvalidity = intval(substr($mbox, $pos + 13));
264                    $mbox = substr($mbox, 0, $pos);
265                }
266                $this->mailbox = rawurldecode($mbox);
267
268                if (isset($data['query'])) {
269                    $this->search = rawurldecode($data['query']);
270                    $parts = array();
271                }
272            } else {
273                $parts = array();
274            }
275
276            if (count($parts)) {
277                foreach ($parts as $val) {
278                    list($k, $v) = explode('=', $val);
279                    $property = Horde_String::lower($k);
280                    $this->$property = $v;
281                }
282            }
283        }
284    }
285
286    /* Serializable methods. */
287
288    /**
289     */
290    public function serialize()
291    {
292        return strval($this);
293    }
294
295    /**
296     */
297    public function unserialize($data)
298    {
299        $this->_parse($data);
300    }
301
302}
303