File: IMAP.php

package info (click to toggle)
imp4 4.2-4lenny3
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 18,252 kB
  • ctags: 5,316
  • sloc: php: 21,340; xml: 19,302; makefile: 68; sql: 14
file content (354 lines) | stat: -rw-r--r-- 10,102 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
<?php

/** Open the mailbox in read-write mode. */
define('IMP_IMAP_READWRITE', 0);

/** Open the IMAP connection without opening a mailbox. */
define('IMP_IMAP_PEEK', 1);

/** Open the mailbox in read-only mode. */
define('IMP_IMAP_READONLY', 2);

/** Open the mailbox in read-only mode, if it hasn't been opened yet. */
define('IMP_IMAP_AUTO', 4);

/**
 * The IMP_IMAP:: class facilitates connections to the IMAP/POP3 server via
 * the c-client PHP extensions.
 *
 * $Horde: imp/lib/IMAP.php,v 1.11.10.18 2008/03/07 15:17:22 slusarz Exp $
 *
 * Copyright 2003-2008 The Horde Project (http://www.horde.org/)
 *
 * See the enclosed file COPYING for license information (GPL). If you
 * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
 *
 * @author  Michael Slusarz <slusarz@horde.org>
 * @package IMP
 */
class IMP_IMAP {

    /**
     * The username for the server.
     *
     * @var string
     */
    var $_user;

    /**
     * The password for the mail server.
     *
     * @var string
     */
    var $_pass;

    /**
     * The current IMAP resource string.
     *
     * @var resource
     */
    var $_stream;

    /**
     * The currently open mailbox.
     *
     * @var string
     */
    var $_openMbox = null;

    /**
     * The IMAP flags set in the currently open mailbox.
     *
     * @var integer
     */
    var $_mboxFlags = null;

    /**
     * Parameters used in the last imap_open() call.
     *
     * @var array
     */
    var $_openparams = array();

    /**
     * Has the shutdown function been registered?
     *
     * @var boolean
     */
    var $_registered = false;

    /**
     * Attempts to return a reference to a concrete IMP_IMAP instance.
     * It will only create a new instance if no IMP_IMAP instance currently
     * exists.
     *
     * This method must be invoked as:
     *   $imp_imap = &IMP_IMAP::singleton();
     *
     * @return IMP_IMAP  The concrete IMP_IMAP reference, or false on error.
     */
    function &singleton($user = null, $pass = null)
    {
        static $instance;

        if (!isset($instance)) {
            $instance = new IMP_IMAP($user, $pass);
        }

        return $instance;
    }

    /**
     * Constructor.
     */
    function IMP_IMAP($user = null, $pass = null)
    {
        if (!is_null($user)) {
            $this->_user = $user;
            $this->_pass = $pass;
        } elseif (isset($_SESSION['imp'])) {
            $this->_user = $_SESSION['imp']['user'];
            $this->_pass = Secret::read(Secret::getKey('imp'), $_SESSION['imp']['pass']);
        }
    }

    /**
     * Open an IMAP stream.
     *
     * @param string $mbox    A mailbox to open.
     * @param integer $flags  Any IMP_IMAP_* flags.
     *
     * @return resource  The return from the imap_open() call.
     */
    function openIMAPStream($mbox = null, $flags = IMP_IMAP_READWRITE)
    {
        $i = -1;
        $ret = false;
        $this->_openparams = array();

        if ($_SESSION['imp']['base_protocol'] == 'pop3') {
            $mbox = 'INBOX';
            $flags = 0;
        } elseif (empty($mbox)) {
            $flags |= IMP_IMAP_PEEK;
        }
        $imap_flags = $this->_toIMAPFlags($flags);

        if (version_compare(PHP_VERSION, '5.2.1') != -1) {
            $ret = @imap_open(IMP::serverString($mbox), $this->_user, $this->_pass, $imap_flags, $_SESSION['imp']['login_tries']);
        } else {
            while (($ret === false) &&
                   !strstr(strtolower(imap_last_error()), 'login failure') &&
                   (++$i < $_SESSION['imp']['login_tries'])) {
                if ($i != 0) {
                    sleep(1);
                }
                $ret = @imap_open(IMP::serverString($mbox), $this->_user, $this->_pass, $imap_flags);
            }
        }

        if ($ret) {
            $this->_openparams = array('f' => $flags, 'm' => $mbox);
        }

        /* Catch c-client errors. */
        if (!$this->_registered) {
            register_shutdown_function(array(&$this, '_onShutdown'));
            $this->_registered = true;
        }

        return $ret;
    }

    /**
     * Perform needed activities on shutdown.
     *
     * @access private
     */
    function _onShutdown()
    {
        $alerts = imap_alerts();
        if (!empty($alerts)) {
            Horde::logMessage('IMAP alerts: ' . implode(' ', $alerts), __FILE__, __LINE__, PEAR_LOG_DEBUG);
        }

        $errors = imap_errors();
        if (!empty($errors)) {
            Horde::logMessage('IMAP errors: ' . implode(' ', $errors), __FILE__, __LINE__, PEAR_LOG_DEBUG);
        }
    }

    /**
     * Change the currently active IMP IMAP stream to a new mailbox (if
     * necessary).
     *
     * @param string $mbox    The new mailbox.
     * @param integer $flags  Any IMP_IMAP_* flags.
     *
     * @return boolean  True on success, false on error.
     */
    function changeMbox($mbox, $flags = IMP_IMAP_READWRITE)
    {
        /* Open a connection if none exists. */
        if (empty($this->_stream)) {
            if (($this->_stream = $this->openIMAPStream($mbox, $flags))) {
                $this->_mboxFlags = $this->_openparams['f'];
                $this->_openMbox = $this->_openparams['m'];
                if (!empty($_SESSION['imp']['imap_server']['timeout'])) {
                    foreach ($_SESSION['imp']['imap_server']['timeout'] as $key => $val) {
                        imap_timeout($key, $val);
                    }
                }
                return true;
            } else {
                return false;
            }
        }

        if ($_SESSION['imp']['base_protocol'] == 'pop3') {
            return true;
        }

        /* Only reopen mailbox if we need to - either we are changing
         * mailboxes or the flags for the current mailbox have changed to an
         * incompatible value. */
        $flags_changed = false;
        if ($this->_mboxFlags != $flags) {
            if ($flags == IMP_IMAP_READWRITE &&
                ($this->_mboxFlags & OP_READONLY ||
                 $this->_mboxFlags & OP_HALFOPEN)) {
                $flags_changed = true;
                $flags = 0;
            } elseif ($flags & IMP_IMAP_READONLY &&
                      !($this->_mboxFlags & OP_READONLY)) {
                $flags_changed = true;
                $flags = OP_READONLY;
            } elseif ($flags & IMP_IMAP_AUTO &&
                      $this->_mboxFlags & OP_HALFOPEN) {
                $flags_changed = true;
                $flags = OP_READONLY;
            }
        }

        if (!$flags_changed) {
            $flags = $this->_toIMAPFlags($flags);
        }

        if ($this->_openMbox != $mbox || $flags_changed) {
            if (version_compare(PHP_VERSION, '5.2.1') != -1) {
                $result = @imap_reopen($this->_stream, IMP::serverString($mbox), $flags, $_SESSION['imp']['login_tries']);
            } else {
                $result = @imap_reopen($this->_stream, IMP::serverString($mbox), $flags);
            }

            if ($result) {
                $this->_openMbox = $mbox;
                $this->_mboxFlags = $flags;
                return true;
            } else {
                return false;
            }
        }

        return true;
    }

    /**
     * Returns the active IMAP resource string.
     *
     * @since IMP 4.2
     *
     * @return resource  The IMAP resource string.
     */
    function stream()
    {
        if (!$this->_stream) {
            $this->_stream = $this->openIMAPStream();
        }
        return $this->_stream;
    }

    /**
     * Returns the list of default IMAP/POP3 protocol connection information.
     * This function can be called statically.
     *
     * @return array  The protocol configuration list.
     */
    function protocolList()
    {
        return array(
            'pop3' => array(
                'name' => _("POP3"),
                'string' => 'pop3',
                'port' => 110,
                'base' => 'POP3'
            ),
            'pop3notls' => array(
                'name' => _("POP3, no TLS"),
                'string' => 'pop3/notls',
                'port' => 110,
                'base' => 'POP3'
            ),
            'pop3sslvalid' => array(
                'name' => _("POP3 over SSL"),
                'string' => 'pop3/ssl',
                'port' => 995,
                'base' => 'POP3'
            ),
            'pop3ssl' => array(
                'name' => _("POP3 over SSL (self-signed certificate)"),
                'string' => 'pop3/ssl/novalidate-cert',
                'port' => 995,
                'base' => 'POP3'
            ),
            'imap' => array(
                'name' => _("IMAP"),
                'string' => 'imap',
                'port' => 143,
                'base' => 'IMAP'
            ),
            'imapnotls' => array(
                'name' => _("IMAP, no TLS"),
                'string' => 'imap/notls',
                'port' => 143,
                'base' => 'IMAP'
            ),
            'imapsslvalid' => array(
                'name' => _("IMAP over SSL"),
                'string' => 'imap/ssl',
                'port' => 993,
                'base' => 'IMAP'
            ),
            'imapssl' => array(
                'name' => _("IMAP over SSL (self-signed certificate)"),
                'string' => 'imap/ssl/novalidate-cert',
                'port' => 993,
                'base' => 'IMAP'
            )
        );
    }

    /**
     * Converts IMP_IMAP_* flags to imap_open() flags.
     *
     * @private
     *
     * @param integer $flags  Any IMP_IMAP_* flags.
     *
     * @return integer  A flag bitmask suitable for imap_open() and
     *                  imap_reopen().
     */
    function _toIMAPFlags($flags)
    {
        $imap_flags = 0;
        if ($flags & IMP_IMAP_PEEK) {
            $imap_flags |= OP_HALFOPEN;
        }
        if ($flags & IMP_IMAP_READONLY ||
            $flags & IMP_IMAP_AUTO) {
            $imap_flags |= OP_READONLY;
        }
        return $imap_flags;
    }

}