Current File : /home/k/a/r/karenpetzb/www/items/category/Protocol.tar
Pop3.php000060400000031230150713636720006103 0ustar00<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 * 
 * @category   Zend
 * @package    Zend_Mail
 * @subpackage Protocol
 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Pop3.php 12539 2008-11-11 02:47:17Z yoshida@zend.co.jp $
 */


/**
 * @category   Zend
 * @package    Zend_Mail
 * @subpackage Protocol
 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Mail_Protocol_Pop3
{
    /**
     * Default timeout in seconds for initiating session
     */
    const TIMEOUT_CONNECTION = 30;
    
    /**
     * saves if server supports top
     * @var null|bool
     */
    public $hasTop = null;

    /**
     * socket to pop3
     * @var null|resource
     */
    protected $_socket;

    /**
     * greeting timestamp for apop
     * @var null|string
     */
    protected $_timestamp;


    /**
     * Public constructor
     *
     * @param  string      $host  hostname of IP address of POP3 server, if given connect() is called
     * @param  int|null    $port  port of POP3 server, null for default (110 or 995 for ssl)
     * @param  bool|string $ssl   use ssl? 'SSL', 'TLS' or false
     * @throws Zend_Mail_Protocol_Exception
     */
    public function __construct($host = '', $port = null, $ssl = false)
    {
        if ($host) {
            $this->connect($host, $port, $ssl);
        }
    }


    /**
     * Public destructor
     */
    public function __destruct()
    {
        $this->logout();
    }


    /**
     * Open connection to POP3 server
     *
     * @param  string      $host  hostname of IP address of POP3 server
     * @param  int|null    $port  of POP3 server, default is 110 (995 for ssl)
     * @param  string|bool $ssl   use 'SSL', 'TLS' or false
     * @return string welcome message
     * @throws Zend_Mail_Protocol_Exception
     */
    public function connect($host, $port = null, $ssl = false)
    {
        if ($ssl == 'SSL') {
            $host = 'ssl://' . $host;
        }

        if ($port === null) {
            $port = $ssl == 'SSL' ? 995 : 110;
        }

        $errno  =  0;
        $errstr = '';
        $this->_socket = @fsockopen($host, $port, $errno, $errstr, self::TIMEOUT_CONNECTION);
        if (!$this->_socket) {
            /**
             * @see Zend_Mail_Protocol_Exception
             */
            require_once 'Zend/Mail/Protocol/Exception.php';
            throw new Zend_Mail_Protocol_Exception('cannot connect to host : ' . $errno . ' : ' . $errstr);
        }

        $welcome = $this->readResponse();

        strtok($welcome, '<');
        $this->_timestamp = strtok('>');
        if (!strpos($this->_timestamp, '@')) {
            $this->_timestamp = null;
        } else {
            $this->_timestamp = '<' . $this->_timestamp . '>';
        }

        if ($ssl === 'TLS') {
            $this->request('STLS');
            $result = stream_socket_enable_crypto($this->_socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
            if (!$result) {
                /**
                 * @see Zend_Mail_Protocol_Exception
                 */
                require_once 'Zend/Mail/Protocol/Exception.php';
                throw new Zend_Mail_Protocol_Exception('cannot enable TLS');
            }
        }

        return $welcome;
    }


    /**
     * Send a request
     *
     * @param string $request your request without newline
     * @return null
     * @throws Zend_Mail_Protocol_Exception
     */
    public function sendRequest($request)
    {
        $result = @fputs($this->_socket, $request . "\r\n");
        if (!$result) {
            /**
             * @see Zend_Mail_Protocol_Exception
             */
            require_once 'Zend/Mail/Protocol/Exception.php';
            throw new Zend_Mail_Protocol_Exception('send failed - connection closed?');
        }
    }


    /**
     * read a response
     *
     * @param  boolean $multiline response has multiple lines and should be read until "<nl>.<nl>"
     * @return string response
     * @throws Zend_Mail_Protocol_Exception
     */
    public function readResponse($multiline = false)
    {
        $result = @fgets($this->_socket);
        if (!is_string($result)) {
            /**
             * @see Zend_Mail_Protocol_Exception
             */
            require_once 'Zend/Mail/Protocol/Exception.php';
            throw new Zend_Mail_Protocol_Exception('read failed - connection closed?');
        }

        $result = trim($result);
        if (strpos($result, ' ')) {
            list($status, $message) = explode(' ', $result, 2);
        } else {
            $status = $result;
            $message = '';
        }

        if ($status != '+OK') {
            /**
             * @see Zend_Mail_Protocol_Exception
             */
            require_once 'Zend/Mail/Protocol/Exception.php';
            throw new Zend_Mail_Protocol_Exception('last request failed');
        }

        if ($multiline) {
            $message = '';
            $line = fgets($this->_socket);
            while ($line && rtrim($line, "\r\n") != '.') {
                if ($line[0] == '.') {
                    $line = substr($line, 1);
                }
                $message .= $line;
                $line = fgets($this->_socket);
            };
        }

        return $message;
    }


    /**
     * Send request and get resposne
     *
     * @see sendRequest(), readResponse()
     *
     * @param  string $request    request
     * @param  bool   $multiline  multiline response?
     * @return string             result from readResponse()
     * @throws Zend_Mail_Protocol_Exception
     */
    public function request($request, $multiline = false)
    {
        $this->sendRequest($request);
        return $this->readResponse($multiline);
    }


    /**
     * End communication with POP3 server (also closes socket)
     *
     * @return null
     */
    public function logout()
    {
        if (!$this->_socket) {
            return;
        }

        try {
            $this->request('QUIT');
        } catch (Zend_Mail_Protocol_Exception $e) {
            // ignore error - we're closing the socket anyway
        }

        fclose($this->_socket);
        $this->_socket = null;
    }


    /**
     * Get capabilities from POP3 server
     *
     * @return array list of capabilities
     * @throws Zend_Mail_Protocol_Exception
     */
    public function capa()
    {
        $result = $this->request('CAPA', true);
        return explode("\n", $result);
    }


    /**
     * Login to POP3 server. Can use APOP
     *
     * @param  string $user      username
     * @param  string $password  password
     * @param  bool   $try_apop  should APOP be tried?
     * @return void
     * @throws Zend_Mail_Protocol_Exception
     */
    public function login($user, $password, $tryApop = true)
    {
        if ($tryApop && $this->_timestamp) {
            try {
                $this->request("APOP $user " . md5($this->_timestamp . $password));
                return;
            } catch (Zend_Mail_Protocol_Exception $e) {
                // ignore
            }
        }

        $result = $this->request("USER $user");
        $result = $this->request("PASS $password");
    }


    /**
     * Make STAT call for message count and size sum
     *
     * @param  int $messages  out parameter with count of messages
     * @param  int $octets    out parameter with size in octects of messages
     * @return void
     * @throws Zend_Mail_Protocol_Exception
     */
    public function status(&$messages, &$octets)
    {
        $messages = 0;
        $octets = 0;
        $result = $this->request('STAT');

        list($messages, $octets) = explode(' ', $result);
    }


    /**
     * Make LIST call for size of message(s)
     *
     * @param  int|null $msgno number of message, null for all
     * @return int|array size of given message or list with array(num => size)
     * @throws Zend_Mail_Protocol_Exception
     */
    public function getList($msgno = null)
    {
        if ($msgno !== null) {
            $result = $this->request("LIST $msgno");

            list(, $result) = explode(' ', $result);
            return (int)$result;
        }

        $result = $this->request('LIST', true);
        $messages = array();
        $line = strtok($result, "\n");
        while ($line) {
            list($no, $size) = explode(' ', trim($line));
            $messages[(int)$no] = (int)$size;
            $line = strtok("\n");
        }

        return $messages;
    }


    /**
     * Make UIDL call for getting a uniqueid
     *
     * @param  int|null $msgno number of message, null for all
     * @return string|array uniqueid of message or list with array(num => uniqueid)
     * @throws Zend_Mail_Protocol_Exception
     */
    public function uniqueid($msgno = null)
    {
        if ($msgno !== null) {
            $result = $this->request("UIDL $msgno");

            list(, $result) = explode(' ', $result);
            return $result;
        }

        $result = $this->request('UIDL', true);

        $result = explode("\n", $result);
        $messages = array();
        foreach ($result as $line) {
            if (!$line) {
                continue;
            }
            list($no, $id) = explode(' ', trim($line), 2);
            $messages[(int)$no] = $id;
        }

        return $messages;

    }


    /**
     * Make TOP call for getting headers and maybe some body lines
     * This method also sets hasTop - before it it's not known if top is supported
     *
     * The fallback makes normale RETR call, which retrieves the whole message. Additional
     * lines are not removed.
     *
     * @param  int  $msgno    number of message
     * @param  int  $lines    number of wanted body lines (empty line is inserted after header lines)
     * @param  bool $fallback fallback with full retrieve if top is not supported
     * @return string message headers with wanted body lines
     * @throws Zend_Mail_Protocol_Exception
     */
    public function top($msgno, $lines = 0, $fallback = false)
    {
        if ($this->hasTop === false) {
            if ($fallback) {
                return $this->retrieve($msgno);
            } else {
                /**
                 * @see Zend_Mail_Protocol_Exception
                 */
                require_once 'Zend/Mail/Protocol/Exception.php';
                throw new Zend_Mail_Protocol_Exception('top not supported and no fallback wanted');
            }
        }
        $this->hasTop = true;

        $lines = (!$lines || $lines < 1) ? 0 : (int)$lines;

        try {
            $result = $this->request("TOP $msgno $lines", true);
        } catch (Zend_Mail_Protocol_Exception $e) {
            $this->hasTop = false;
            if ($fallback) {
                $result = $this->retrieve($msgno);
            } else {
                throw $e;
            }
        }

        return $result;
    }


    /**
     * Make a RETR call for retrieving a full message with headers and body
     *
     * @deprecated since 1.1.0; this method has a typo - please use retrieve()
     * @param  int $msgno  message number
     * @return string message
     * @throws Zend_Mail_Protocol_Exception
     */
    public function retrive($msgno)
    {
        return $this->retrieve($msgno);
    }


    /**
     * Make a RETR call for retrieving a full message with headers and body
     *
     * @param  int $msgno  message number
     * @return string message
     * @throws Zend_Mail_Protocol_Exception
     */
    public function retrieve($msgno)
    {
        $result = $this->request("RETR $msgno", true);
        return $result;
    }

    /**
     * Make a NOOP call, maybe needed for keeping the server happy
     *
     * @return null
     * @throws Zend_Mail_Protocol_Exception
     */
    public function noop()
    {
        $this->request('NOOP');
    }


    /**
     * Make a DELE count to remove a message
     *
     * @return null
     * @throws Zend_Mail_Protocol_Exception
     */
    public function delete($msgno)
    {
        $this->request("DELE $msgno");
    }


    /**
     * Make RSET call, which rollbacks delete requests
     *
     * @return null
     * @throws Zend_Mail_Protocol_Exception
     */
    public function undelete()
    {
        $this->request('RSET');
    }
}
Smtp/Auth/Login.php000060400000004730150713636720010163 0ustar00<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 * 
 * @category   Zend
 * @package    Zend_Mail
 * @subpackage Protocol
 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Login.php 8064 2008-02-16 10:58:39Z thomas $
 */


/**
 * @see Zend_Mail_Protocol_Smtp
 */
require_once 'Zend/Mail/Protocol/Smtp.php';


/**
 * Performs LOGIN authentication
 *
 * @category   Zend
 * @package    Zend_Mail
 * @subpackage Protocol
 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Mail_Protocol_Smtp_Auth_Login extends Zend_Mail_Protocol_Smtp
{
    /**
     * LOGIN username
     *
     * @var string
     */
    protected $_username;


    /**
     * LOGIN password
     *
     * @var string
     */
    protected $_password;


    /**
     * Constructor.
     *
     * @param  string $host   (Default: 127.0.0.1)
     * @param  int    $port   (Default: null)
     * @param  array  $config Auth-specific parameters
     * @return void
     */
    public function __construct($host = '127.0.0.1', $port = null, $config = null)
    {
        if (is_array($config)) {
            if (isset($config['username'])) {
                $this->_username = $config['username'];
            }
            if (isset($config['password'])) {
                $this->_password = $config['password'];
            }
        }

        parent::__construct($host, $port, $config);
    }


    /**
     * Perform LOGIN authentication with supplied credentials
     *
     * @return void
     */
    public function auth()
    {
        // Ensure AUTH has not already been initiated.
        parent::auth();

        $this->_send('AUTH LOGIN');
        $this->_expect(334);
        $this->_send(base64_encode($this->_username));
        $this->_expect(334);
        $this->_send(base64_encode($this->_password));
        $this->_expect(235);
        $this->_auth = true;
    }
}
Smtp/Auth/Crammd5.php000060400000006133150713636720010402 0ustar00<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 * 
 * @category   Zend
 * @package    Zend_Mail
 * @subpackage Protocol
 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Crammd5.php 8064 2008-02-16 10:58:39Z thomas $
 */


/**
 * @see Zend_Mail_Protocol_Smtp
 */
require_once 'Zend/Mail/Protocol/Smtp.php';


/**
 * Performs CRAM-MD5 authentication
 *
 * @category   Zend
 * @package    Zend_Mail
 * @subpackage Protocol
 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Mail_Protocol_Smtp_Auth_Crammd5 extends Zend_Mail_Protocol_Smtp
{
    /**
     * Constructor.
     *
     * @param  string $host   (Default: 127.0.0.1)
     * @param  int    $port   (Default: null)
     * @param  array  $config Auth-specific parameters
     * @return void
     */
    public function __construct($host = '127.0.0.1', $port = null, $config = null)
    {
        if (is_array($config)) {
            if (isset($config['username'])) {
                $this->_username = $config['username'];
            }
            if (isset($config['password'])) {
                $this->_password = $config['password'];
            }
        }

        parent::__construct($host, $port, $config);
    }


    /**
     * @todo Perform CRAM-MD5 authentication with supplied credentials
     *
     * @return void
     */
    public function auth()
    {
        // Ensure AUTH has not already been initiated.
        parent::auth();

        $this->_send('AUTH CRAM-MD5');
        $challenge = $this->_expect(334);
        $challenge = base64_decode($challenge);
        $digest = $this->_hmacMd5($this->_password, $challenge);
        $this->_send(base64_encode($this->_username . ' ' . $digest));
        $this->_expect(235);
        $this->_auth = true;
    }


    /**
     * Prepare CRAM-MD5 response to server's ticket
     *
     * @param  string $key   Challenge key (usually password)
     * @param  string $data  Challenge data
     * @param  string $block Length of blocks
     * @return string
     */
    protected function _hmacMd5($key, $data, $block = 64)
    {
        if (strlen($key) > 64) {
            $key = pack('H32', md5($key));
        } elseif (strlen($key) < 64) {
            $key = str_pad($key, $block, chr(0));
        }

        $k_ipad = substr($key, 0, 64) ^ str_repeat(chr(0x36), 64);
        $k_opad = substr($key, 0, 64) ^ str_repeat(chr(0x5C), 64);

        $inner = pack('H32', md5($k_ipad . $data));
        $digest = md5($k_opad . $inner);

        return $digest;
    }
}
Smtp/Auth/Plain.php000060400000004651150713636720010160 0ustar00<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 * 
 * @category   Zend
 * @package    Zend_Mail
 * @subpackage Protocol
 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Plain.php 8064 2008-02-16 10:58:39Z thomas $
 */


/**
 * @see Zend_Mail_Protocol_Smtp
 */
require_once 'Zend/Mail/Protocol/Smtp.php';


/**
 * Performs PLAIN authentication
 *
 * @category   Zend
 * @package    Zend_Mail
 * @subpackage Protocol
 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Mail_Protocol_Smtp_Auth_Plain extends Zend_Mail_Protocol_Smtp
{
    /**
     * PLAIN username
     *
     * @var string
     */
    protected $_username;


    /**
     * PLAIN password
     *
     * @var string
     */
    protected $_password;


    /**
     * Constructor.
     *
     * @param  string $host   (Default: 127.0.0.1)
     * @param  int    $port   (Default: null)
     * @param  array  $config Auth-specific parameters
     * @return void
     */
    public function __construct($host = '127.0.0.1', $port = null, $config = null)
    {
        if (is_array($config)) {
            if (isset($config['username'])) {
                $this->_username = $config['username'];
            }
            if (isset($config['password'])) {
                $this->_password = $config['password'];
            }
        }

        parent::__construct($host, $port, $config);
    }


    /**
     * Perform PLAIN authentication with supplied credentials
     *
     * @return void
     */
    public function auth()
    {
        // Ensure AUTH has not already been initiated.
        parent::auth();

        $this->_send('AUTH PLAIN');
        $this->_expect(334);
        $this->_send(base64_encode(chr(0) . $this->_username . chr(0) . $this->_password));
        $this->_expect(235);
        $this->_auth = true;
    }
}
Smtp.php000060400000027147150713636720006221 0ustar00<?php

/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 * 
 * @category   Zend
 * @package    Zend_Mail
 * @subpackage Protocol
 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Smtp.php 11196 2008-09-02 00:56:25Z yoshida@zend.co.jp $
 */


/**
 * @see Zend_Mime
 */
require_once 'Zend/Mime.php';


/**
 * @see Zend_Mail_Protocol_Abstract
 */
require_once 'Zend/Mail/Protocol/Abstract.php';


/**
 * Smtp implementation of Zend_Mail_Protocol_Abstract
 *
 * Minimum implementation according to RFC2821: EHLO, MAIL FROM, RCPT TO, DATA, RSET, NOOP, QUIT
 * 
 * @category   Zend
 * @package    Zend_Mail
 * @subpackage Protocol
 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Mail_Protocol_Smtp extends Zend_Mail_Protocol_Abstract
{
    /**
     * The transport method for the socket
     *
     * @var string
     */
    protected $_transport = 'tcp';


    /**
     * Indicates that a session is requested to be secure
     *
     * @var string
     */
    protected $_secure;


    /**
     * Indicates an smtp session has been started by the HELO command
     *
     * @var boolean
     */
    protected $_sess = false;


    /**
     * Indicates the HELO command has been issues
     *
     * @var unknown_type
     */
    protected $_helo = false;


    /**
     * Indicates an smtp AUTH has been issued and authenticated
     *
     * @var unknown_type
     */
    protected $_auth = false;


    /**
     * Indicates a MAIL command has been issued
     *
     * @var unknown_type
     */
    protected $_mail = false;


    /**
     * Indicates one or more RCTP commands have been issued
     *
     * @var unknown_type
     */
    protected $_rcpt = false;


    /**
     * Indicates that DATA has been issued and sent
     *
     * @var unknown_type
     */
    protected $_data = null;


    /**
     * Constructor.
     *
     * @param  string  $host
     * @param  integer $port
     * @param  array   $config
     * @return void
     * @throws Zend_Mail_Protocol_Exception
     */
    public function __construct($host = '127.0.0.1', $port = null, array $config = array())
    {
        if (isset($config['ssl'])) {
            switch (strtolower($config['ssl'])) {
                case 'tls':
                    $this->_secure = 'tls';
                    break;

                case 'ssl':
                    $this->_transport = 'ssl';
                    $this->_secure = 'ssl';
                    if ($port == null) {
                        $port = 465;
                    }
                    break;

                default:
                    /**
                     * @see Zend_Mail_Protocol_Exception
                     */
                    require_once 'Zend/Mail/Protocol/Exception.php';
                    throw new Zend_Mail_Protocol_Exception($config['ssl'] . ' is unsupported SSL type');
                    break;
            }
        }

        // If no port has been specified then check the master PHP ini file. Defaults to 25 if the ini setting is null.
        if ($port == null) {
            if (($port = ini_get('smtp_port')) == '') {
                $port = 25;
            }
        }

        parent::__construct($host, $port);
    }


    /**
     * Connect to the server with the parameters given in the constructor.
     *
     * @return boolean
     */
    public function connect()
    {
        return $this->_connect($this->_transport . '://' . $this->_host . ':'. $this->_port);
    }


    /**
     * Initiate HELO/EHLO sequence and set flag to indicate valid smtp session
     *
     * @param  string $host The client hostname or IP address (default: 127.0.0.1)
     * @throws Zend_Mail_Protocol_Exception
     * @return void
     */
    public function helo($host = '127.0.0.1')
    {
        // Respect RFC 2821 and disallow HELO attempts if session is already initiated.
        if ($this->_sess === true) {
            /**
             * @see Zend_Mail_Protocol_Exception
             */
            require_once 'Zend/Mail/Protocol/Exception.php';
            throw new Zend_Mail_Protocol_Exception('Cannot issue HELO to existing session');
        }

        // Validate client hostname
        if (!$this->_validHost->isValid($host)) {
            /**
             * @see Zend_Mail_Protocol_Exception
             */
            require_once 'Zend/Mail/Protocol/Exception.php';
            throw new Zend_Mail_Protocol_Exception(join(', ', $this->_validHost->getMessages()));
        }

        // Initiate helo sequence
        $this->_expect(220, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
        $this->_ehlo($host);

        // If a TLS session is required, commence negotiation
        if ($this->_secure == 'tls') {
            $this->_send('STARTTLS');
            $this->_expect(220, 180);
            if (!stream_socket_enable_crypto($this->_socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
                /**
                 * @see Zend_Mail_Protocol_Exception
                 */
                require_once 'Zend/Mail/Protocol/Exception.php';
                throw new Zend_Mail_Protocol_Exception('Unable to connect via TLS');
            }
            $this->_ehlo($host);
        }

        $this->_startSession();
        $this->auth();
    }


    /**
     * Send EHLO or HELO depending on capabilities of smtp host
     *
     * @param  string $host The client hostname or IP address (default: 127.0.0.1)
     * @throws Zend_Mail_Protocol_Exception
     * @return void
     */
    protected function _ehlo($host)
    {
        // Support for older, less-compliant remote servers. Tries multiple attempts of EHLO or HELO.
        try {
            $this->_send('EHLO ' . $host);
            $this->_expect(250, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
        } catch (Zend_Mail_Protocol_Exception $e) {
            $this->_send('HELO ' . $host);
            $this->_expect(250, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
        } catch (Zend_Mail_Protocol_Exception $e) {
            throw $e;
        }
    }


    /**
     * Issues MAIL command
     *
     * @param  string $from Sender mailbox
     * @throws Zend_Mail_Protocol_Exception
     * @return void
     */
    public function mail($from)
    {
        if ($this->_sess !== true) {
            /**
             * @see Zend_Mail_Protocol_Exception
             */
            require_once 'Zend/Mail/Protocol/Exception.php';
            throw new Zend_Mail_Protocol_Exception('A valid session has not been started');
        }

        $this->_send('MAIL FROM:<' . $from . '>');
        $this->_expect(250, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2

        // Set mail to true, clear recipients and any existing data flags as per 4.1.1.2 of RFC 2821
        $this->_mail = true;
        $this->_rcpt = false;
        $this->_data = false;
    }


    /**
     * Issues RCPT command
     *
     * @param  string $to Receiver(s) mailbox
     * @throws Zend_Mail_Protocol_Exception
     * @return void
     */
    public function rcpt($to)
    {
        if ($this->_mail !== true) {
            /**
             * @see Zend_Mail_Protocol_Exception
             */
            require_once 'Zend/Mail/Protocol/Exception.php';
            throw new Zend_Mail_Protocol_Exception('No sender reverse path has been supplied');
        }

        // Set rcpt to true, as per 4.1.1.3 of RFC 2821
        $this->_send('RCPT TO:<' . $to . '>');
        $this->_expect(array(250, 251), 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
        $this->_rcpt = true;
    }


    /**
     * Issues DATA command
     *
     * @param  string $data
     * @throws Zend_Mail_Protocol_Exception
     * @return void
     */
    public function data($data)
    {
        // Ensure recipients have been set
        if ($this->_rcpt !== true) {
            /**
             * @see Zend_Mail_Protocol_Exception
             */
            require_once 'Zend/Mail/Protocol/Exception.php';
            throw new Zend_Mail_Protocol_Exception('No recipient forward path has been supplied');
        }

        $this->_send('DATA');
        $this->_expect(354, 120); // Timeout set for 2 minutes as per RFC 2821 4.5.3.2

        foreach (explode(Zend_Mime::LINEEND, $data) as $line) {
            if (strpos($line, '.') === 0) {
                // Escape lines prefixed with a '.'
                $line = '.' . $line;
            }
            $this->_send($line);
        }

        $this->_send('.');
        $this->_expect(250, 600); // Timeout set for 10 minutes as per RFC 2821 4.5.3.2
        $this->_data = true;
    }


    /**
     * Issues the RSET command end validates answer
     *
     * Can be used to restore a clean smtp communication state when a transaction has been cancelled or commencing a new transaction.
     *
     * @return void
     */
    public function rset()
    {
        $this->_send('RSET');
        // MS ESMTP doesn't follow RFC, see [ZF-1377]
        $this->_expect(array(250, 220));

        $this->_mail = false;
        $this->_rcpt = false;
        $this->_data = false;
    }


    /**
     * Issues the NOOP command end validates answer
     *
     * Not used by Zend_Mail, could be used to keep a connection alive or check if it is still open.
     *
     * @return void
     */
    public function noop()
    {
        $this->_send('NOOP');
        $this->_expect(250, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
    }


    /**
     * Issues the VRFY command end validates answer
     *
     * Not used by Zend_Mail.
     *
     * @param  string $user User Name or eMail to verify
     * @return void
     */
    public function vrfy($user)
    {
        $this->_send('VRFY ' . $user);
        $this->_expect(array(250, 251, 252), 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
    }


    /**
     * Issues the QUIT command and clears the current session
     *
     * @return void
     */
    public function quit()
    {
        if ($this->_sess) {
            $this->_send('QUIT');
            $this->_expect(221, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
            $this->_stopSession();
        }
    }


    /**
     * Default authentication method
     *
     * This default method is implemented by AUTH adapters to properly authenticate to a remote host.
     *
     * @throws Zend_Mail_Protocol_Exception
     * @return void
     */
    public function auth()
    {
        if ($this->_auth === true) {
            /**
             * @see Zend_Mail_Protocol_Exception
             */
            require_once 'Zend/Mail/Protocol/Exception.php';
            throw new Zend_Mail_Protocol_Exception('Already authenticated for this session');
        }
    }


    /**
     * Closes connection
     *
     * @return void
     */
    public function disconnect()
    {
        $this->_disconnect();
    }


    /**
     * Start mail session
     *
     * @return void
     */
    protected function _startSession()
    {
        $this->_sess = true;
    }


    /**
     * Stop mail session
     *
     * @return void
     */
    protected function _stopSession()
    {
        $this->_sess = false;
    }
}
Imap.php000060400000065710150713636720006162 0ustar00<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 * 
 * @category   Zend
 * @package    Zend_Mail
 * @subpackage Protocol
 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Imap.php 12539 2008-11-11 02:47:17Z yoshida@zend.co.jp $
 */


/**
 * @category   Zend
 * @package    Zend_Mail
 * @subpackage Protocol
 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Mail_Protocol_Imap
{
    /**
     * Default timeout in seconds for initiating session
     */
    const TIMEOUT_CONNECTION = 30;
    
    /**
     * socket to imap server
     * @var resource|null
     */
    protected $_socket;

    /**
     * counter for request tag
     * @var int
     */
    protected $_tagCount = 0;

    /**
     * Public constructor
     *
     * @param  string   $host  hostname of IP address of IMAP server, if given connect() is called
     * @param  int|null $port  port of IMAP server, null for default (143 or 993 for ssl)
     * @param  bool     $ssl   use ssl? 'SSL', 'TLS' or false
     * @throws Zend_Mail_Protocol_Exception
     */
    function __construct($host = '', $port = null, $ssl = false)
    {
        if ($host) {
            $this->connect($host, $port, $ssl);
        }
    }

    /**
     * Public destructor
     */
    public function __destruct()
    {
        $this->logout();
    }

    /**
     * Open connection to POP3 server
     *
     * @param  string      $host  hostname of IP address of POP3 server
     * @param  int|null    $port  of IMAP server, default is 143 (993 for ssl)
     * @param  string|bool $ssl   use 'SSL', 'TLS' or false
     * @return string welcome message
     * @throws Zend_Mail_Protocol_Exception
     */
    public function connect($host, $port = null, $ssl = false)
    {
        if ($ssl == 'SSL') {
            $host = 'ssl://' . $host;
        }

        if ($port === null) {
            $port = $ssl === 'SSL' ? 993 : 143;
        }

        $errno  =  0;
        $errstr = '';
        $this->_socket = @fsockopen($host, $port, $errno, $errstr, self::TIMEOUT_CONNECTION);
        if (!$this->_socket) {
            /**
             * @see Zend_Mail_Protocol_Exception
             */
            require_once 'Zend/Mail/Protocol/Exception.php';
            throw new Zend_Mail_Protocol_Exception('cannot connect to host : ' . $errno . ' : ' . $errstr);
        }

        if (!$this->_assumedNextLine('* OK')) {
            /**
             * @see Zend_Mail_Protocol_Exception
             */
            require_once 'Zend/Mail/Protocol/Exception.php';
            throw new Zend_Mail_Protocol_Exception('host doesn\'t allow connection');
        }

        if ($ssl === 'TLS') {
            $result = $this->requestAndResponse('STARTTLS');
            $result = $result && stream_socket_enable_crypto($this->_socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
            if (!$result) {
                /**
                 * @see Zend_Mail_Protocol_Exception
                 */
                require_once 'Zend/Mail/Protocol/Exception.php';
                throw new Zend_Mail_Protocol_Exception('cannot enable TLS');
            }
        }
    }

    /**
     * get the next line from socket with error checking, but nothing else
     *
     * @return string next line
     * @throws Zend_Mail_Protocol_Exception
     */
    protected function _nextLine()
    {
        $line = @fgets($this->_socket);
        if ($line === false) {
            /**
             * @see Zend_Mail_Protocol_Exception
             */
            require_once 'Zend/Mail/Protocol/Exception.php';
            throw new Zend_Mail_Protocol_Exception('cannot read - connection closed?');
        }

        return $line;
    }

    /**
     * get next line and assume it starts with $start. some requests give a simple
     * feedback so we can quickly check if we can go on.
     *
     * @param  string $start the first bytes we assume to be in the next line
     * @return bool line starts with $start
     * @throws Zend_Mail_Protocol_Exception
     */
    protected function _assumedNextLine($start)
    {
        $line = $this->_nextLine();
        return strpos($line, $start) === 0;
    }

    /**
     * get next line and split the tag. that's the normal case for a response line
     *
     * @param  string $tag tag of line is returned by reference
     * @return string next line
     * @throws Zend_Mail_Protocol_Exception
     */
    protected function _nextTaggedLine(&$tag)
    {
        $line = $this->_nextLine();

        // seperate tag from line
        list($tag, $line) = explode(' ', $line, 2);

        return $line;
    }

    /**
     * split a given line in tokens. a token is literal of any form or a list
     *
     * @param  string $line line to decode
     * @return array tokens, literals are returned as string, lists as array
     * @throws Zend_Mail_Protocol_Exception
     */
    protected function _decodeLine($line)
    {
        $tokens = array();
        $stack = array();

        /*
            We start to decode the response here. The unterstood tokens are:
                literal
                "literal" or also "lit\\er\"al"
                {bytes}<NL>literal
                (literals*)
            All tokens are returned in an array. Literals in braces (the last unterstood
            token in the list) are returned as an array of tokens. I.e. the following response:
                "foo" baz {3}<NL>bar ("f\\\"oo" bar)
            would be returned as:
                array('foo', 'baz', 'bar', array('f\\\"oo', 'bar'));
                
            // TODO: add handling of '[' and ']' to parser for easier handling of response text 
        */
        //  replace any trailling <NL> including spaces with a single space
        $line = rtrim($line) . ' ';
        while (($pos = strpos($line, ' ')) !== false) {
            $token = substr($line, 0, $pos);
            while ($token[0] == '(') {
                array_push($stack, $tokens);
                $tokens = array();
                $token = substr($token, 1);
            }
            if ($token[0] == '"') {
                if (preg_match('%^"((.|\\\\|\\")*?)" *%', $line, $matches)) {
                    $tokens[] = $matches[1];
                    $line = substr($line, strlen($matches[0]));
                    continue;
                }
            }
            if ($token[0] == '{') {
                $endPos = strpos($token, '}');
                $chars = substr($token, 1, $endPos - 1);
                if (is_numeric($chars)) {
                    $token = '';
                    while (strlen($token) < $chars) {
                        $token .= $this->_nextLine();
                    }
                    $line = '';
                    if (strlen($token) > $chars) {
                        $line = substr($token, $chars);
                        $token = substr($token, 0, $chars);
                    } else {
                        $line .= $this->_nextLine();
                    }
                    $tokens[] = $token;
                    $line = trim($line) . ' ';
                    continue;
                }
            }
            if ($stack && $token[strlen($token) - 1] == ')') {
                // closing braces are not seperated by spaces, so we need to count them
                $braces = strlen($token);
                $token = rtrim($token, ')');
                // only count braces if more than one
                $braces -= strlen($token) + 1;
                // only add if token had more than just closing braces
                if ($token) {
                    $tokens[] = $token;
                }
                $token = $tokens;
                $tokens = array_pop($stack);
                // special handline if more than one closing brace
                while ($braces-- > 0) {
                    $tokens[] = $token;
                    $token = $tokens;
                    $tokens = array_pop($stack);
                }
            }
            $tokens[] = $token;
            $line = substr($line, $pos + 1);
        }

        // maybe the server forgot to send some closing braces
        while ($stack) {
            $child = $tokens;
            $tokens = array_pop($stack);
            $tokens[] = $child;
        }

        return $tokens;
    }

    /**
     * read a response "line" (could also be more than one real line if response has {..}<NL>)
     * and do a simple decode
     *
     * @param  array|string  $tokens    decoded tokens are returned by reference, if $dontParse
     *                                  is true the unparsed line is returned here
     * @param  string        $wantedTag check for this tag for response code. Default '*' is
     *                                  continuation tag.
     * @param  bool          $dontParse if true only the unparsed line is returned $tokens
     * @return bool if returned tag matches wanted tag
     * @throws Zend_Mail_Protocol_Exception
     */
    public function readLine(&$tokens = array(), $wantedTag = '*', $dontParse = false)
    {
        $line = $this->_nextTaggedLine($tag);
        if (!$dontParse) {
            $tokens = $this->_decodeLine($line);
        } else {
            $tokens = $line;
        }

        // if tag is wanted tag we might be at the end of a multiline response
        return $tag == $wantedTag;
    }

    /**
     * read all lines of response until given tag is found (last line of response)
     *
     * @param  string       $tag       the tag of your request
     * @param  string|array $filter    you can filter the response so you get only the
     *                                 given response lines
     * @param  bool         $dontParse if true every line is returned unparsed instead of
     *                                 the decoded tokens
     * @return null|bool|array tokens if success, false if error, null if bad request
     * @throws Zend_Mail_Protocol_Exception
     */
    public function readResponse($tag, $dontParse = false)
    {
        $lines = array();
        while (!$this->readLine($tokens, $tag, $dontParse)) {
            $lines[] = $tokens;
        }

        if ($dontParse) {
            // last to chars are still needed for response code
            $tokens = array(substr($tokens, 0, 2));
        }
        // last line has response code
        if ($tokens[0] == 'OK') {
            return $lines ? $lines : true;
        } else if ($tokens[0] == 'NO'){
            return false;
        }
        return null;
    }

    /**
     * send a request
     *
     * @param  string $command your request command
     * @param  array  $tokens  additional parameters to command, use escapeString() to prepare
     * @param  string $tag     provide a tag otherwise an autogenerated is returned
     * @return null
     * @throws Zend_Mail_Protocol_Exception
     */
    public function sendRequest($command, $tokens = array(), &$tag = null)
    {
        if (!$tag) {
            ++$this->_tagCount;
            $tag = 'TAG' . $this->_tagCount;
        }

        $line = $tag . ' ' . $command;

        foreach ($tokens as $token) {
            if (is_array($token)) {
                if (@fputs($this->_socket, $line . ' ' . $token[0] . "\r\n") === false) {
                    /**
                     * @see Zend_Mail_Protocol_Exception
                     */
                    require_once 'Zend/Mail/Protocol/Exception.php';
                    throw new Zend_Mail_Protocol_Exception('cannot write - connection closed?');
                }
                if (!$this->_assumedNextLine('+ ')) {
                    /**
                     * @see Zend_Mail_Protocol_Exception
                     */
                    require_once 'Zend/Mail/Protocol/Exception.php';
                    throw new Zend_Mail_Protocol_Exception('cannot send literal string');
                }
                $line = $token[1];
            } else {
                $line .= ' ' . $token;
            }
        }

        if (@fputs($this->_socket, $line . "\r\n") === false) {
            /**
             * @see Zend_Mail_Protocol_Exception
             */
            require_once 'Zend/Mail/Protocol/Exception.php';
            throw new Zend_Mail_Protocol_Exception('cannot write - connection closed?');
        }
    }

    /**
     * send a request and get response at once
     *
     * @param  string $command   command as in sendRequest()
     * @param  array  $tokens    parameters as in sendRequest()
     * @param  bool   $dontParse if true unparsed lines are returned instead of tokens
     * @return mixed response as in readResponse()
     * @throws Zend_Mail_Protocol_Exception
     */
    public function requestAndResponse($command, $tokens = array(), $dontParse = false)
    {
        $this->sendRequest($command, $tokens, $tag);
        $response = $this->readResponse($tag, $dontParse);

        return $response;
    }

    /**
     * escape one or more literals i.e. for sendRequest
     *
     * @param  string|array $string the literal/-s
     * @return string|array escape literals, literals with newline ar returned
     *                      as array('{size}', 'string');
     */
    public function escapeString($string)
    {
        if (func_num_args() < 2) {
            if (strpos($string, "\n") !== false) {
                return array('{' . strlen($string) . '}', $string);
            } else {
                return '"' . str_replace(array('\\', '"'), array('\\\\', '\\"'), $string) . '"';
            }
        }
        $result = array();
        foreach (func_get_args() as $string) {
            $result[] = $this->escapeString($string);
        }
        return $result;
    }

    /**
     * escape a list with literals or lists
     *
     * @param  array $list list with literals or lists as PHP array
     * @return string escaped list for imap
     */
    public function escapeList($list)
    {
        $result = array();
        foreach ($list as $k => $v) {
            if (!is_array($v)) {
//              $result[] = $this->escapeString($v);
                $result[] = $v;
                continue;
            }
            $result[] = $this->escapeList($v);
        }
        return '(' . implode(' ', $result) . ')';
    }

    /**
     * Login to IMAP server.
     *
     * @param  string $user      username
     * @param  string $password  password
     * @return bool success
     * @throws Zend_Mail_Protocol_Exception
     */
    public function login($user, $password)
    {
        return $this->requestAndResponse('LOGIN', $this->escapeString($user, $password), true);
    }

    /**
     * logout of imap server
     *
     * @return bool success
     */
    public function logout()
    {
        $result = false;
        if ($this->_socket) {
            try {
                $result = $this->requestAndResponse('LOGOUT', array(), true);
            } catch (Zend_Mail_Protocol_Exception $e) {
                // ignoring exception
            }
            fclose($this->_socket);
            $this->_socket = null;
        }
        return $result;
    }


    /**
     * Get capabilities from IMAP server
     *
     * @return array list of capabilities
     * @throws Zend_Mail_Protocol_Exception
     */
    public function capability()
    {
        $response = $this->requestAndResponse('CAPABILITY');

        if (!$response) {
            return $response;
        }

        $capabilities = array();
        foreach ($response as $line) {
            $capabilities = array_merge($capabilities, $line);
        }
        return $capabilities;
    }

    /**
     * Examine and select have the same response. The common code for both
     * is in this method
     *
     * @param  string $command can be 'EXAMINE' or 'SELECT' and this is used as command
     * @param  string $box which folder to change to or examine
     * @return bool|array false if error, array with returned information
     *                    otherwise (flags, exists, recent, uidvalidity)
     * @throws Zend_Mail_Protocol_Exception
     */
    public function examineOrSelect($command = 'EXAMINE', $box = 'INBOX')
    {
        $this->sendRequest($command, array($this->escapeString($box)), $tag);

        $result = array();
        while (!$this->readLine($tokens, $tag)) {
            if ($tokens[0] == 'FLAGS') {
                array_shift($tokens);
                $result['flags'] = $tokens;
                continue;
            }
            switch ($tokens[1]) {
                case 'EXISTS':
                case 'RECENT':
                    $result[strtolower($tokens[1])] = $tokens[0];
                    break;
                case '[UIDVALIDITY':
                    $result['uidvalidity'] = (int)$tokens[2];
                    break;
                default:
                    // ignore
            }
        }

        if ($tokens[0] != 'OK') {
            return false;
        }
        return $result;
    }

    /**
     * change folder
     *
     * @param  string $box change to this folder
     * @return bool|array see examineOrselect()
     * @throws Zend_Mail_Protocol_Exception
     */
    public function select($box = 'INBOX')
    {
        return $this->examineOrSelect('SELECT', $box);
    }

    /**
     * examine folder
     *
     * @param  string $box examine this folder
     * @return bool|array see examineOrselect()
     * @throws Zend_Mail_Protocol_Exception
     */
    public function examine($box = 'INBOX')
    {
        return $this->examineOrSelect('EXAMINE', $box);
    }

    /**
     * fetch one or more items of one or more messages
     *
     * @param  string|array $items items to fetch from message(s) as string (if only one item)
     *                             or array of strings
     * @param  int          $from  message for items or start message if $to !== null
     * @param  int|null     $to    if null only one message ($from) is fetched, else it's the
     *                             last message, INF means last message avaible
     * @return string|array if only one item of one message is fetched it's returned as string
     *                      if items of one message are fetched it's returned as (name => value)
     *                      if one items of messages are fetched it's returned as (msgno => value)
     *                      if items of messages are fetchted it's returned as (msgno => (name => value))
     * @throws Zend_Mail_Protocol_Exception
     */
    public function fetch($items, $from, $to = null)
    {
        if (is_array($from)) {
            $set = implode(',', $from);
        } else if ($to === null) {
            $set = (int)$from;
        } else if ($to === INF) {
            $set = (int)$from . ':*';
        } else {
            $set = (int)$from . ':' . (int)$to;
        }

        $items = (array)$items;
        $itemList = $this->escapeList($items);

        $this->sendRequest('FETCH', array($set, $itemList), $tag);

        $result = array();
        while (!$this->readLine($tokens, $tag)) {
            // ignore other responses
            if ($tokens[1] != 'FETCH') {
                continue;
            }
            // ignore other messages
            if ($to === null && !is_array($from) && $tokens[0] != $from) {
                continue;
            }
            // if we only want one item we return that one directly
            if (count($items) == 1) {
                if ($tokens[2][0] == $items[0]) {
                    $data = $tokens[2][1];
                } else {
                    // maybe the server send an other field we didn't wanted
                    $count = count($tokens[2]);
                    // we start with 2, because 0 was already checked
                    for ($i = 2; $i < $count; $i += 2) {
                        if ($tokens[2][$i] != $items[0]) {
                            continue;
                        }
                        $data = $tokens[2][$i + 1];
                        break;
                    }
                }
            } else {
                $data = array();
                while (key($tokens[2]) !== null) {
                    $data[current($tokens[2])] = next($tokens[2]);
                    next($tokens[2]);
                }
            }
            // if we want only one message we can ignore everything else and just return
            if ($to === null && !is_array($from) && $tokens[0] == $from) {
                // we still need to read all lines
                while (!$this->readLine($tokens, $tag));
                return $data;
            }
            $result[$tokens[0]] = $data;
        }

        if ($to === null && !is_array($from)) {
            /**
             * @see Zend_Mail_Protocol_Exception
             */
            require_once 'Zend/Mail/Protocol/Exception.php';
            throw new Zend_Mail_Protocol_Exception('the single id was not found in response');
        }

        return $result;
    }

    /**
     * get mailbox list
     *
     * this method can't be named after the IMAP command 'LIST', as list is a reserved keyword
     *
     * @param  string $reference mailbox reference for list
     * @param  string $mailbox   mailbox name match with wildcards
     * @return array mailboxes that matched $mailbox as array(globalName => array('delim' => .., 'flags' => ..))
     * @throws Zend_Mail_Protocol_Exception
     */
    public function listMailbox($reference = '', $mailbox = '*')
    {
        $result = array();
        $list = $this->requestAndResponse('LIST', $this->escapeString($reference, $mailbox));
        if (!$list || $list === true) {
            return $result;
        }

        foreach ($list as $item) {
            if (count($item) != 4 || $item[0] != 'LIST') {
                continue;
            }
            $result[$item[3]] = array('delim' => $item[2], 'flags' => $item[1]);
        }

        return $result;
    }

    /**
     * set flags
     *
     * @param  array       $flags  flags to set, add or remove - see $mode
     * @param  int         $from   message for items or start message if $to !== null
     * @param  int|null    $to     if null only one message ($from) is fetched, else it's the
     *                             last message, INF means last message avaible
     * @param  string|null $mode   '+' to add flags, '-' to remove flags, everything else sets the flags as given
     * @param  bool        $silent if false the return values are the new flags for the wanted messages
     * @return bool|array new flags if $silent is false, else true or false depending on success
     * @throws Zend_Mail_Protocol_Exception
     */
    public function store(array $flags, $from, $to = null, $mode = null, $silent = true)
    {
        $item = 'FLAGS';
        if ($mode == '+' || $mode == '-') {
            $item = $mode . $item;
        }
        if ($silent) {
            $item .= '.SILENT';
        }

        $flags = $this->escapeList($flags);
        $set = (int)$from;
        if ($to != null) {
            $set .= ':' . ($to == INF ? '*' : (int)$to);
        }

        $result = $this->requestAndResponse('STORE', array($set, $item, $flags), $silent);

        if ($silent) {
            return $result ? true : false;
        }

        $tokens = $result;
        $result = array();
        foreach ($tokens as $token) {
            if ($token[1] != 'FETCH' || $token[2][0] != 'FLAGS') {
                continue;
            }
            $result[$token[0]] = $token[2][1];
        }

        return $result;
    }

    /**
     * append a new message to given folder
     *
     * @param string $folder  name of target folder
     * @param string $message full message content
     * @param array  $flags   flags for new message
     * @param string $date    date for new message
     * @return bool success
     * @throws Zend_Mail_Protocol_Exception
     */
    public function append($folder, $message, $flags = null, $date = null)
    {
        $tokens = array();
        $tokens[] = $this->escapeString($folder);
        if ($flags !== null) {
            $tokens[] = $this->escapeList($flags);
        }
        if ($date !== null) {
            $tokens[] = $this->escapeString($date);
        }
        $tokens[] = $this->escapeString($message);

        return $this->requestAndResponse('APPEND', $tokens, true);
    }

    /**
     * copy message set from current folder to other folder
     *
     * @param string   $folder destination folder
     * @param int|null $to     if null only one message ($from) is fetched, else it's the
     *                         last message, INF means last message avaible
     * @return bool success
     * @throws Zend_Mail_Protocol_Exception
     */
    public function copy($folder, $from, $to = null)
    {
        $set = (int)$from;
        if ($to != null) {
            $set .= ':' . ($to == INF ? '*' : (int)$to);
        }

        return $this->requestAndResponse('COPY', array($set, $this->escapeString($folder)), true);
    }

    /**
     * create a new folder (and parent folders if needed)
     *
     * @param string $folder folder name
     * @return bool success
     */
    public function create($folder)
    {
        return $this->requestAndResponse('CREATE', array($this->escapeString($folder)), true);
    }

    /**
     * rename an existing folder
     *
     * @param string $old old name
     * @param string $new new name
     * @return bool success
     */
    public function rename($old, $new)
    {
        return $this->requestAndResponse('RENAME', $this->escapeString($old, $new), true);
    }

    /**
     * remove a folder
     *
     * @param string $folder folder name
     * @return bool success
     */
    public function delete($folder)
    {
        return $this->requestAndResponse('DELETE', array($this->escapeString($folder)), true);
    }

    /**
     * permanently remove messages
     *
     * @return bool success
     */
    public function expunge()
    {
        // TODO: parse response?
        return $this->requestAndResponse('EXPUNGE');
    }

    /**
     * send noop
     *
     * @return bool success
     */
    public function noop()
    {
        // TODO: parse response
        return $this->requestAndResponse('NOOP');
    }

    /**
     * do a search request
     *
     * This method is currently marked as internal as the API might change and is not
     * safe if you don't take precautions.
     *
     * @internal
     * @return array message ids
     */
    public function search(array $params)
    {
        $response = $this->requestAndResponse('SEARCH', $params);
        if (!$response) {
            return $response;
        }
        
        foreach ($response as $ids) {
            if ($ids[0] == 'SEARCH') {
                array_shift($ids);
                return $ids;
            }
        }
        return array();
    }

}
Abstract.php000060400000023302150713636720007026 0ustar00<?php

/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 * 
 * @category   Zend
 * @package    Zend_Mail
 * @subpackage Protocol
 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Abstract.php 12395 2008-11-07 23:58:38Z nico $
 */


/**
 * @see Zend_Validate
 */
require_once 'Zend/Validate.php';


/**
 * @see Zend_Validate_Hostname
 */
require_once 'Zend/Validate/Hostname.php';


/**
 * Zend_Mail_Protocol_Abstract
 *
 * Provides low-level methods for concrete adapters to communicate with a remote mail server and track requests and responses.
 * 
 * @category   Zend
 * @package    Zend_Mail
 * @subpackage Protocol
 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Abstract.php 12395 2008-11-07 23:58:38Z nico $
 * @todo Implement proxy settings
 */
abstract class Zend_Mail_Protocol_Abstract
{
    /**
     * Mail default EOL string
     */
    const EOL = "\r\n";


    /**
     * Default timeout in seconds for initiating session
     */
    const TIMEOUT_CONNECTION = 30;


    /**
     * Hostname or IP address of remote server
     * @var string
     */
    protected $_host;


    /**
     * Port number of connection
     * @var integer
     */
    protected $_port;


    /**
     * Instance of Zend_Validate to check hostnames
     * @var Zend_Validate
     */
    protected $_validHost;


    /**
     * Socket connection resource
     * @var resource
     */
    protected $_socket;


    /**
     * Last request sent to server
     * @var string
     */
    protected $_request;


    /**
     * Array of server responses to last request
     * @var array
     */
    protected $_response;


    /**
     * String template for parsing server responses using sscanf (default: 3 digit code and response string)
     * @var resource
     */
    protected $_template = '%d%s';


    /**
     * Log of mail requests and server responses for a session
     * @var string
     */
    private $_log;


    /**
     * Constructor.
     *
     * @param  string  $host OPTIONAL Hostname of remote connection (default: 127.0.0.1)
     * @param  integer $port OPTIONAL Port number (default: null)
     * @throws Zend_Mail_Protocol_Exception
     * @return void
     */
    public function __construct($host = '127.0.0.1', $port = null)
    {
        $this->_validHost = new Zend_Validate();
        $this->_validHost->addValidator(new Zend_Validate_Hostname(Zend_Validate_Hostname::ALLOW_ALL));

        if (!$this->_validHost->isValid($host)) {
            /**
             * @see Zend_Mail_Protocol_Exception
             */
            require_once 'Zend/Mail/Protocol/Exception.php';
            throw new Zend_Mail_Protocol_Exception(join(', ', $this->_validHost->getMessages()));
        }

        $this->_host = $host;
        $this->_port = $port;
    }


    /**
     * Class destructor to cleanup open resources
     *
     * @return void
     */
    public function __destruct()
    {
        $this->_disconnect();
    }


    /**
     * Create a connection to the remote host
     *
     * Concrete adapters for this class will implement their own unique connect scripts, using the _connect() method to create the socket resource.
     */
    abstract public function connect();


    /**
     * Retrieve the last client request
     *
     * @return string
     */
    public function getRequest()
    {
        return $this->_request;
    }


    /**
     * Retrieve the last server response
     *
     * @return array
     */
    public function getResponse()
    {
        return $this->_response;
    }


    /**
     * Retrieve the transaction log
     *
     * @return string
     */
    public function getLog()
    {
        return $this->_log;
    }


    /**
     * Reset the transaction log
     *
     * @return void
     */
    public function resetLog()
    {
        $this->_log = '';
    }


    /**
     * Connect to the server using the supplied transport and target
     *
     * An example $remote string may be 'tcp://mail.example.com:25' or 'ssh://hostname.com:2222'
     *
     * @param  string $remote Remote
     * @throws Zend_Mail_Protocol_Exception
     * @return boolean
     */
    protected function _connect($remote)
    {
        $errorNum = 0;
        $errorStr = '';

        // open connection
        $this->_socket = @stream_socket_client($remote, $errorNum, $errorStr, self::TIMEOUT_CONNECTION);

        if ($this->_socket === false) {
            if ($errorNum == 0) {
                $errorStr = 'Could not open socket';
            }
            /**
             * @see Zend_Mail_Protocol_Exception
             */
            require_once 'Zend/Mail/Protocol/Exception.php';
            throw new Zend_Mail_Protocol_Exception($errorStr);
        }

        if (($result = stream_set_timeout($this->_socket, self::TIMEOUT_CONNECTION)) === false) {
            /**
             * @see Zend_Mail_Protocol_Exception
             */
            require_once 'Zend/Mail/Protocol/Exception.php';
            throw new Zend_Mail_Protocol_Exception('Could not set stream timeout');
        }

        return $result;
    }


    /**
     * Disconnect from remote host and free resource
     *
     * @return void
     */
    protected function _disconnect()
    {
        if (is_resource($this->_socket)) {
            fclose($this->_socket);
        }
    }


    /**
     * Send the given request followed by a LINEEND to the server.
     *
     * @param  string $request
     * @throws Zend_Mail_Protocol_Exception
     * @return integer|boolean Number of bytes written to remote host
     */
    protected function _send($request)
    {
        if (!is_resource($this->_socket)) {
            /**
             * @see Zend_Mail_Protocol_Exception
             */
            require_once 'Zend/Mail/Protocol/Exception.php';
            throw new Zend_Mail_Protocol_Exception('No connection has been established to ' . $this->_host);
        }

        $this->_request = $request;

        $result = fwrite($this->_socket, $request . self::EOL);

        // Save request to internal log
        $this->_log .= $request . self::EOL;

        if ($result === false) {
            /**
             * @see Zend_Mail_Protocol_Exception
             */
            require_once 'Zend/Mail/Protocol/Exception.php';
            throw new Zend_Mail_Protocol_Exception('Could not send request to ' . $this->_host);
        }

        return $result;
    }


    /**
     * Get a line from the stream.
     *
     * @var    integer $timeout Per-request timeout value if applicable
     * @throws Zend_Mail_Protocol_Exception
     * @return string
     */
    protected function _receive($timeout = null)
    {
        if (!is_resource($this->_socket)) {
            /**
             * @see Zend_Mail_Protocol_Exception
             */
            require_once 'Zend/Mail/Protocol/Exception.php';
            throw new Zend_Mail_Protocol_Exception('No connection has been established to ' . $this->_host);
        }

        // Adapters may wish to supply per-commend timeouts according to appropriate RFC
        if ($timeout !== null) {
           stream_set_timeout($this->_socket, $timeout);
        }

        // Retrieve response
        $reponse = fgets($this->_socket, 1024);

        // Save request to internal log
        $this->_log .= $reponse;

        // Check meta data to ensure connection is still valid
        $info = stream_get_meta_data($this->_socket);

        if (!empty($info['timed_out'])) {
            /**
             * @see Zend_Mail_Protocol_Exception
             */
            require_once 'Zend/Mail/Protocol/Exception.php';
            throw new Zend_Mail_Protocol_Exception($this->_host . ' has timed out');
        }

        if ($reponse === false) {
            /**
             * @see Zend_Mail_Protocol_Exception
             */
            require_once 'Zend/Mail/Protocol/Exception.php';
            throw new Zend_Mail_Protocol_Exception('Could not read from ' . $this->_host);
        }

        return $reponse;
    }


    /**
     * Parse server response for successful codes
     *
     * Read the response from the stream and check for expected return code.
     * Throws a Zend_Mail_Protocol_Exception if an unexpected code is returned.
     *
     * @param  string|array $code One or more codes that indicate a successful response
     * @throws Zend_Mail_Protocol_Exception
     * @return string Last line of response string
     */
    protected function _expect($code, $timeout = null)
    {
        $this->_response = array();
        $cmd = '';
        $msg = '';

        if (!is_array($code)) {
            $code = array($code);
        }

        do {
            $this->_response[] = $result = $this->_receive($timeout);
            sscanf($result, $this->_template, $cmd, $msg);

            if ($cmd === null || !in_array($cmd, $code)) {
                /**
                 * @see Zend_Mail_Protocol_Exception
                 */
                require_once 'Zend/Mail/Protocol/Exception.php';
                throw new Zend_Mail_Protocol_Exception($result);
            }

        } while (strpos($msg, '-') === 0); // The '-' message prefix indicates an information string instead of a response string.

        return $msg;
    }
}
Exception.php000060400000002203150713636720007216 0ustar00<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 * 
 * @category   Zend
 * @package    Zend_Mail
 * @subpackage Protocol
 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Exception.php 8064 2008-02-16 10:58:39Z thomas $
 */


/**
 * @see Zend_Exception
 */
require_once 'Zend/Mail/Exception.php';


/**
 * @category   Zend
 * @package    Zend_Mail
 * @subpackage Protocol
 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Mail_Protocol_Exception extends Zend_Mail_Exception
{}

JsonStream.php000060400000016614150714226170007353 0ustar00<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Wildfire
 * @subpackage Protocol
 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */

/** Zend_Wildfire_Exception */
require_once 'Zend/Wildfire/Exception.php';

/** Zend_Wildfire_Plugin_Interface */
require_once 'Zend/Wildfire/Plugin/Interface.php';

/** Zend_Wildfire_Channel_Interface */
require_once 'Zend/Wildfire/Channel/Interface.php';

/** Zend_Json */
require_once 'Zend/Json.php';

/**
 * Encodes messages into the Wildfire JSON Stream Communication Protocol.
 * 
 * @category   Zend
 * @package    Zend_Wildfire
 * @subpackage Protocol
 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Wildfire_Protocol_JsonStream
{
    /**
     * The protocol URI for this protocol
     */
    const PROTOCOL_URI = 'http://meta.wildfirehq.org/Protocol/JsonStream/0.2';

    /**
     * All messages to be sent.
     * @var array
     */
    protected $_messages = array();

    /**
     * Plugins that are using this protocol
     * @var array
     */
    protected $_plugins = array();
    
    /**
     * Register a plugin that uses this protocol
     * 
     * @param Zend_Wildfire_Plugin_Interface $plugin The plugin to be registered
     * @return boolean Returns TRUE if plugin was registered, false if it was already registered
     */
    public function registerPlugin(Zend_Wildfire_Plugin_Interface $plugin)
    {
        if (in_array($plugin,$this->_plugins)) {
            return false;
        }
        $this->_plugins[] = $plugin;
        return true;
    }

    /**
     * Record a message with the given data in the given structure
     * 
     * @param Zend_Wildfire_Plugin_Interface $plugin The plugin recording the message
     * @param string $structure The structure to be used for the data
     * @param array $data The data to be recorded
     * @return boolean Returns TRUE if message was recorded
     */
    public function recordMessage(Zend_Wildfire_Plugin_Interface $plugin, $structure, $data)
    {
        if(!isset($this->_messages[$structure])) {
            $this->_messages[$structure] = array();  
        }
        
        $uri = $plugin->getUri();
        
        if(!isset($this->_messages[$structure][$uri])) {
            $this->_messages[$structure][$uri] = array();  
        }
        
        $this->_messages[$structure][$uri][] = $this->_encode($data);
        return true;
    }

    /**
     * Remove all qued messages
     * 
     * @param Zend_Wildfire_Plugin_Interface $plugin The plugin for which to clear messages
     * @return boolean Returns TRUE if messages were present
     */
    public function clearMessages(Zend_Wildfire_Plugin_Interface $plugin)
    {
        $uri = $plugin->getUri();
        
        $present = false;
        foreach ($this->_messages as $structure => $messages) {
                
            if(!isset($this->_messages[$structure][$uri])) {
                continue;
            }
            
            $present = true;
            
            unset($this->_messages[$structure][$uri]);
            
            if (!$this->_messages[$structure]) {
                unset($this->_messages[$structure]);
            }
        }
        return $present;
    }

    /**
     * Get all qued messages
     * 
     * @return mixed Returns qued messages or FALSE if no messages are qued
     */
    public function getMessages()
    {
        if (!$this->_messages) {
            return false;
        }
        return $this->_messages;
    }

    /**
     * Use the JSON encoding scheme for the value specified
     *
     * @param mixed $value The value to be encoded
     * @return string  The encoded value
     */
    protected function _encode($value)
    {
        return Zend_Json::encode($value, true, array('silenceCyclicalExceptions'=>true));
    }

    /**
     * Retrieves all formatted data ready to be sent by the channel.
     * 
     * @param Zend_Wildfire_Channel_Interface $channel The instance of the channel that will be transmitting the data
     * @return mixed Returns the data to be sent by the channel.
     * @throws Zend_Wildfire_Exception
     */
    public function getPayload(Zend_Wildfire_Channel_Interface $channel)
    {
        if (!$channel instanceof Zend_Wildfire_Channel_HttpHeaders) {
            throw new Zend_Wildfire_Exception('The '.get_class($channel).' channel is not supported by the '.get_class($this).' protocol.');          
        }
        
        if ($this->_plugins) {
            foreach ($this->_plugins as $plugin) {
                $plugin->flushMessages(self::PROTOCOL_URI);
            }
        }
        
        if (!$this->_messages) {
            return false;
        }
                
        $protocol_index = 1;
        $structure_index = 1;
        $plugin_index = 1;
        $message_index = 1;

        $payload = array();

        $payload[] = array('Protocol-'.$protocol_index, self::PROTOCOL_URI);
        
        foreach ($this->_messages as $structure_uri => $plugin_messages ) {
            
            $payload[] = array($protocol_index.'-Structure-'.$structure_index, $structure_uri);

            foreach ($plugin_messages as $plugin_uri => $messages ) {
                
                $payload[] = array($protocol_index.'-Plugin-'.$plugin_index, $plugin_uri);
          
                foreach ($messages as $message) {
                  
                    $parts = explode("\n",chunk_split($message, 5000, "\n"));
                                    
                    for ($i=0 ; $i<count($parts) ; $i++) {

                        $part = $parts[$i];
                        if ($part) {

                            $msg = '';

                            if (count($parts)>2) {
                                $msg = (($i==0)?strlen($message):'')
                                       . '|' . $part . '|'
                                       . (($i<count($parts)-2)?'\\':'');
                            } else {
                                $msg = strlen($part) . '|' . $part . '|';
                            }

                            $payload[] = array($protocol_index . '-'
                                               . $structure_index . '-'
                                               . $plugin_index . '-'
                                               . $message_index,
                                               $msg);

                            $message_index++;
                            
                            if ($message_index > 99999) {
                                throw new Zend_Wildfire_Exception('Maximum number (99,999) of messages reached!');             
                            }
                        }
                    }
                }
                $plugin_index++;
            }
            $structure_index++;
        }

        return $payload;
    }

}